SFML community forums

Help => Graphics => Topic started by: deadmau5 on November 27, 2012, 03:46:40 pm

Title: sf::Sprite vector reference to sf::Texture vector
Post by: deadmau5 on November 27, 2012, 03:46:40 pm
Well, I'm having a bit of a head-scratch here.
I understand that Sprites are references to Textures and the Textures need to be initialized for the Sprites to draw.

In this case, I have a vector of Textures in class TexMgr in which I store all tilesheets:
TexMgr.h:
std::vector<sf::Texture> tileSheets;
std::map<unsigned long, unsigned long> tileIDs;

TexMgr.cpp:
void TexMgr::addTilesheet(sf::Texture &tilesheet) {
        tileSheets.push_back(tilesheet);
}
 

Now I want to store each tile in each tilesheet of the previous vector into a seperate Sprite vector:
TexMgr.h:
std::vector<sf::Sprite> sprTiles;
TexMgr.cpp:
void TexMgr::addTile(sf::Sprite &tile, unsigned long id) {
        sprTiles.push_back(tile);
        tileIDs[id] = sprTiles.size() - 1;
}
 

and finally draw the sprite using:
sf::Sprite* TexMgr::getTileSpr(unsigned long id) {
        return &sprTiles[tileIDs[id]];
}
 

I don't think this is the correct way of doing things because the rendered Sprite is white.
Could anyone lighten me up, any help is appreciated.
Title: Re: sf::Sprite vector reference to sf::Texture vector
Post by: cire on November 27, 2012, 04:15:58 pm
If a push_back to tileSheets results in a tileSheets needing to expand, all the references to textures in sprTiles will be invalidated.

You might try using a std::deque for tileSheets.
Title: Re: sf::Sprite vector reference to sf::Texture vector
Post by: gyscos on November 27, 2012, 04:35:02 pm
I think a vector of Texture is pretty dangerous in the first place. I'd say a vector of Texture* would be a little easier, since you don't have to worry about such invalidation-on-destructor and so on. Deleting the texture on removal is a small price to pay.
Title: Re: sf::Sprite vector reference to sf::Texture vector
Post by: Nexus on November 27, 2012, 04:50:48 pm
Deleting the texture on removal is a small price to pay.
Which is not necessary with std::unique_ptr<Texture> or another STL container.
Title: Re: sf::Sprite vector reference to sf::Texture vector
Post by: eXpl0it3r on November 27, 2012, 04:51:10 pm
I think a vector of Texture is pretty dangerous in the first place. I'd say a vector of Texture* would be a little easier, since you don't have to worry about such invalidation-on-destructor and so on. Deleting the texture on removal is a small price to pay.
Both are bad ideas! Nowadays there's just no need to manually manage your memory, it's actually even depreciated. :-\

Either use a static number of textures and size the size of the vector in advance or use a recent compiler and std::unique_ptr. ;)
Title: Re: sf::Sprite vector reference to sf::Texture vector
Post by: deadmau5 on November 27, 2012, 05:20:26 pm
If a push_back to tileSheets results in a tileSheets needing to expand, all the references to textures in sprTiles will be invalidated.

You might try using a std::deque for tileSheets.
Thanks, I had no idea it would be invalidated by expanding. Solved.
Title: Re: sf::Sprite vector reference to sf::Texture vector
Post by: ichineko on November 28, 2012, 01:42:42 am
yep, std::vector storage is required to be contiguous in memory (makes interfacing with C API's much simpler), which implies copying everything over when the vector needs to be resized internally :)

I don't personally like the design decision to have the texture destroyed in that manner, but it is what it is.  I second exploiters recommendation of using a Smart Pointer.  Even if you don't have access to a compiler that allows you to use the new C++ features (where they're built in), there are plenty of smart pointer implementations laying around for you to use.  It's kind of a pain, but you can also pull specific parts of BOOST out without using the entire library (they have a tool for doing so).

It might be more work than it's worth depending on the scope of your project, but lets call that the long winded version of "you should really be using smart pointers, and they're available for just about any C++ compiler made in the last 12+ years".