SFML community forums

Help => Graphics => Topic started by: aSpookyMan on July 27, 2020, 01:30:10 am

Title: Sprite being drawn as a white square even though sprite points to texture
Post by: aSpookyMan on July 27, 2020, 01:30:10 am
I have this struct containing a sprite and a texture:
struct Layer
{
        Layer(const char* _path, sf::View& view) : deviation{ 0.0f }, mod{ 1 } {
                txtr.loadFromFile(_path);
                spr.setTexture(txtr);
                txtr.setRepeated(true);

                scale = { view.getSize().y / txtr.getSize().y ,
                                  view.getSize().y / txtr.getSize().y };

                sf::Vector2f pos(view.getCenter().x - view.getSize().x, view.getCenter().y + view.getSize().y / 2);
                sf::Vector2f sprdim(txtr.getSize().x* scale.x, txtr.getSize().y* scale.y);

                spr.setOrigin({0.0f, sprdim.y});
                spr.setPosition(pos);
                spr.setTextureRect({ 0, 0, static_cast<int>(txtr.getSize().x),
                                                               static_cast<int>(txtr.getSize().y) });
                spr.setScale(scale);
        }

        sf::Vector2f scale;

        sf::Sprite spr;
        sf::Texture txtr;

        float deviation;

        unsigned mod;
};
 
Then I made a vector of 'Layer' in the following class:
class Parallax {
public:

        std::vector<Layer> layers;

        sf::Sprite sprite;//test
        sf::Texture t;
       
        Player player;

        float deviation = 0.0f;
        float speed = 0.5f;
        unsigned mod = 1;

        bool canMove;

        void Init(Player& player, sf::View& view);
        void Update(const float& dt, sf::View& view);
        void Draw(sf::RenderTarget& target);
};
 
And lastly, the definition:
#include "Parallax.h"

void Parallax::Init(Player& player, sf::View& view) {
       
        this->player = player;

        //Further-most layers added first
        layers.push_back(Layer("Res/Textures/Parallax/glacial_mountains.png", view));

}
void Parallax::Update(const float& dt, sf::View& view) {
        for (size_t i = 0; i < layers.size(); i++) {
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) && player.canMoveLeft) {
                        layers.at(i).deviation += this->speed * i * dt;
                        this->canMove = true;
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) && player.canMoveRight) {
                        layers.at(i).deviation -= this->speed * i * dt;
                        this->canMove = true;
                }
                else this->canMove = false;

                if (canMove) layers.at(i).spr.move(deviation * dt, 0.0f);
               
                sf::Vector2f sprpos(layers.at(i).spr.getPosition());
                sf::Vector2f sprdim(layers.at(i).txtr.getSize().x * layers.at(i).spr.getScale().x,
                        layers.at(i).txtr.getSize().y * layers.at(i).spr.getScale().y);

                if (sprpos.x + sprdim.x < view.getCenter().x + view.getSize().x / 2) {
                        layers.at(i).mod++;
                        layers.at(i).spr.setTextureRect({ 0, 0, static_cast<int>(layers.at(i).txtr.getSize().x * layers.at(i).mod),
                                                                                                        static_cast<int>(layers.at(i).txtr.getSize().y) });
                }
        }
}
void Parallax::Draw(sf::RenderTarget& target) {
        for (auto& i : this->layers) target.draw(i.spr);
}
 
I don't understand how that could possibly lose the pointer to its texture, since the texture itself is not a temporary variable. Maybe it's some dumb mistake that I'm making, but I can't really see it.
I tried pinting
std::cout << sprite.getTexture() << "\n";
and the texture's memory address was outputted just fine. Any ideas to what might be causing this?

Title: Re: Sprite being drawn as a white square even though sprite points to texture
Post by: Laurent on July 27, 2020, 08:20:31 am
It's because std::vector<Layer> will move it's elements when it needs more contiguous space in memory. You should handle copy or move construction for your Layer class, or better, store textures outside them (especially if they share the same ones).

The address returned by Sprite::getTexture() never magically goes back to null of course, the problem is that there's no more valid texture at that address, because it moved somewhere else. Your sprite thinks it points to a valid texture, but it's just garbage, and therefore it needs to be updated (which never happens in your code).
Title: Re: Sprite being drawn as a white square even though sprite points to texture
Post by: aSpookyMan on July 27, 2020, 05:39:18 pm
Yeah that makes sense, thank you!