Search code examples
c++texturesgame-developmentsfml

Why can't textures be loaded properly by functions other than one that draws window?


I am making a chess game using c++ and SFML. When I try to locate texture loading inside some class function, I get a white rectangle instead of the texture. Here is my code:

void GameRender::load_textures(){
    Texture texture;
    if (!texture.loadFromFile("../graphics/textures/board.png")){
        throw;
    }
    boardSprite.setTexture(texture);
}

void GameRender::draw_board(){
    load_textures();

    Event event;
    Vector2u prevWinSize = window.getSize();
    const float desiredAspectRatio = 1.0f / 1.0f;
    const float basicScaleX = static_cast<float>(prevWinSize.x) / boardSprite.getGlobalBounds().width;
    const float basicScaleY = static_cast<float>(prevWinSize.y) / boardSprite.getGlobalBounds().height;
    boardSprite.setScale(basicScaleX, basicScaleY);

    while (window.isOpen()){
        while (window.pollEvent(event)){
            if (event.type == Event::Closed){
                window.close();
            } else if (event.type == Event::Resized){
                set_window_size(desiredAspectRatio, prevWinSize);
            }
            if (event.type == Event::KeyPressed){
                if (event.key.code == sf::Keyboard::Escape){
                    window.close();
                }
            }
        }
        window.clear();
        window.draw(boardSprite);
        window.display();
    }
}

And this is how it looks when I run it: enter image description here

However, it works as intended if I put texture loading inside draw_board() function:

void GameRender::draw_board(){
    Texture texture;
    if (!texture.loadFromFile("../graphics/textures/board.png")){
        throw;
    }
    boardSprite.setTexture(texture);

    Event event;
    // remaining code is the same

enter image description here

How it can be resolved, so I can make code more readable by loading textures in a separate function?


Solution

  • void sf::Sprite::setTexture(const Texture& texture, bool resetRect = false )
    Change the source texture of the sprite.

    The texture argument refers to a texture that must exist as long as the sprite uses it. Indeed, the sprite doesn't store its own copy of the texture, but rather keeps a pointer to the one that you passed to this function. If the source texture is destroyed and the sprite tries to use it, the behavior is undefined.

    In order to get around that, keep the Texture as a member variable in GameRender instead of making it local to the load_textures function. When it's local to the load_textures function, it will be destroyed when the function returns and you'll then have the undefined behavior mentioned above.