0
\$\begingroup\$

My problem is that when I try to render my sf::Sprite it only renders a white box in my window.

I did some reading on this and couldn't really find anything that helped.

Some said that it's because of the sf::Texture variable being in a local scope but mine is in a .h file, which isn't a local scope (I think, at least...)

Someone also mentioned std::vectors somehow destroying the sf::Texture 's, but my sf::Texture is not in a std::vector.

However my class which contains sf::Texture is a object inside a std::vector but I don't know if that matters or not.


In my Sprite.h I have defined my sf::Sprite, sf::Texture and sf::Image like this :

sf::Sprite sprite;
sf::Texture texture;
sf::Image image;

and I load an image in like this :

if (!image.loadFromFile(PATH))
    std::cout << "Could not load image file : " << PATH << std::endl;

texture.loadFromImage(image);
sprite.setTexture(texture);

I render the sf::Sprite like this :

    for (int i = 0; i < entities.size(); i++)
    {
        entities[i].Draw();
    }

Lastly, here's my std::vector of my "sprite objects".

std::vector<Sprite>entities;
entities.push_back(Sprite(&window, sf::Vector2f(100, 100), 0, "Res/Images/Face.bmp"));

The picture file is a .bmp file, and the path to the file is valid.


(I did check both google and this forum for posts like this but none of them helped me.)

\$\endgroup\$
0
1
\$\begingroup\$

Your Sprite class contains a sf::Texture object which is moved by the std::vector<Sprite> container.

You're still placing sf::Texture inside a std::vector, just indirectly.

When the std::vector gets resized Sprite objects get copied to a new larger buffer at new addresses. But the texture pointer inside sf::Sprite still points to the old address where the sf::Texture used to be originally.

You can fix this by using an std::vector<Sprite *> instead which will copy the pointers to objects rather than the objects themselves.

std::vector<Sprite *> entities;

and allocate your Sprite objects on the heap as such:

entities.push_back(new Sprite(&window, sf::Vector2f(100, 100), 0, "Res/Images/Face.bmp"));

(Note the new keyword above.)

To destroy:

delete entities[i]; // Delete first
entities.erase(entities.begin()+i); // remove from array (std::vector)

to draw:

for (int i = 0; i < entities.size(); ++i)
{
    entities[i]->Draw();
}

(Note the -> operator instead of . operator above. And use the prefix operator ++i whenever possible)

This will make sure every Sprite object stay in the same spot in memory once created. Only pointers to them get stored inside the std::vector.

It also makes adding and removing objects faster as less data is moved around.

You just have to remember to delete the Sprite objects before erasing the entry in entities or you will leak memory.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.