SFML community forums
Help => General => Topic started by: GregStuart on May 06, 2016, 12:44:50 pm
-
Hey, I have a weird issue.
So, I have this method that should make 8x8 sprites from a spritesheet and put them into a list of sprites, which it does.
however, when I spawn a sprite, It shares the same texture as the very last Sprite in the list.
So, Sprite 1 should have texture 1, but it has the texture of sprite 128.
This is the same for every sprite in my list.
How would I resolve this?
If I was going to take a guess, I'd need to also store the texture somehow? perhaps in a second textures vector? but then whenever I loaded a sprite I'd need to set the texture of it equal to the texture at the same position in the sister vector? I feel like I'm overcomplicating this/doing it the wrong way.
http://imgur.com/gfkiCbb
(http://imgur.com/gfkiCbb)
Any help would be appreciated.
void SpriteMaker(int dimension, int scale)
{
int c = 0, r = 0, y = sheetIMG.getSize().y, x = sheetIMG.getSize().x;
do
{
for (int i = 0; i <= (x * y) / 64; i++)
{
if (r == 64)
break;
if (!tex.loadFromImage(sheetIMG, IntRect(c, r, dimension, dimension)))
break;
else
{
Sprite spr;
spr.setTexture(tex);
spr.setScale(scale, scale);
Spritesheet.push_back(spr);
c += dimension;
if (c == x) { c = 0; r+=8; };
}
}
} while (r < y);
}
-
Are you reusing one and the same sf::Texture for each sprite?
If yes, the texture doesn't get copied into the sf::Sprite the sprite only holds a pointer/reference to it, so if you change the texture, it will be changed for every sprite.
-
Basically, the texture is applied to the sprite, then the sprite is added to the list.
I reuse that tex object for all 128 sprites, so yes, it is overwritten 128 times.
Does this mean I need to have an instance of every texture in it's own array?
I'm changing my Game to a singleton object atm.
-
Yes for 2 reasons
1.) you must have the sperate array for textures, because the sprite holds only a const pointer to texture.
2.) texture gets destroyed when its instance goes out of scope.
-
Due to the lack of help.
I kinda did it "My way"
And I've probably done it in a very inefficient way.
I made this to hold the textures:
vector<Texture> Textures;
and in my MakeSprite method, after getting the texture, I push it onto the back, just like I do with sprites.
Textures.push_back(tex);
Sprite spr;
spr.setTexture(Textures.at(i));
then this basically sets the texture to the correct one.
Sprite Game::RenderSprite(int i, int x, int y)
{
Spritesheet.at(i).setTexture(Textures.at(i));
Spritesheet.at(i).setPosition(x, y);
return Spritesheet.at(i);
}
The issue is, this is now getting called every frame.
int Game::MainLoop() {
srand(time(NULL));
RenderWindow window(VideoMode(1920, 1080), "Conduit");
MakeCircle(10, 100, 100, Color::White);
if (!LoadSpritesheet())
{
return 1;
}
while (window.isOpen()) {
Event event;
while (window.pollEvent(event)) {
if (event.type == Event::Closed)
window.close();
}
window.clear();
window.draw(RenderSprite(2, 10, 10));
window.draw(RenderSprite(4, 10, 40));
window.draw(RenderSprite(10, 10, 80));
window.draw(RenderSprite(11, 10, 120));
DrawCircles(window);
window.display();
}
}
But I guess it works?
-
There are seseveral problems with your solution.
- your vector holding textures is problematic since if the vector copies sprites when it needs to grow you'll invalidate any pointers held by sprites to elements in the vector. You can mitigate that either by holding pointers (or better yet, smart pointers) to textures in your vector or by making sure the vector never resizes by calling .reserve() on ot before you push_back the textures and then never push more into it than you reserve.
- don't use srand()/rand() they produce really poor random numbers and time(NULL) is a horrible seed. Use the facilities in the <tt>random</tt> header instead. See these two links:
http://en.cppreference.com/w/cpp/numeric/random
https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
- setting textures on all sprites every frame is inefficient and needless.
-
What would you suggest I do?
Have a bool or something which I set to false after first render, and then only set to true again if the sprite has actually been changed?
-
If you can, get a copy of the SFML Game Devleopment (http://www.sfml-dev.org/learn.php#books) book. It has a good explanation on resource management (the source for which can be seen here (https://github.com/SFML/SFML-Game-Development-Book/tree/master/02_Resources))