Search code examples
c++cmakesfml

sfml - image cannot display


I create a sfml project with cmake on windows, but the image cannot display.

src/main.cpp

#include "game.hpp"
#include <SFML/Graphics.hpp>

int main() {
    Game game;

    sf::Clock clock;
    sf::Time elapsed;
    float frametime = 1.0f / 60.0f;

    while (game.window.isOpen()) {
        sf::Event event;
        while (game.window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                game.window.close();
            }
        }

        // 1. 事件处理
        game.handleInput();

        // 2. 更新物理逻辑
        if (elapsed.asSeconds() >= frametime) {
            elapsed -= sf::seconds(frametime);
            game.update(); // 60次/秒
        }
        elapsed += clock.restart();

        // 3. 渲染
        game.window.clear();
        game.render();
        game.window.display();
    }
    return 0;
}

src/game.hpp

class Game {
  public:
    sf::RenderWindow window;

    sf::Sprite s;

    Game() {
        window.create({320, 480}, "hello");

        sf::Texture t;
        t.loadFromFile("images/tiles.png");
        s.setTexture(t);
    }

    void handleInput() {}

    void update() {}

    void render() { window.draw(s); }
};

If I put draw code into main.cpp then it works. Like this:

src/main.cpp

       ...
        // 3. 渲染
        game.window.clear();
        // game.render();
        sf::Texture t;
        t.loadFromFile("images/tiles.png");

        sf::Sprite s(t);
        game.window.draw(s);
        game.window.display();
       ...

I want to know how it work


Solution

  • sfml has a FAQ for this The White Square Problem

    This is a common mistake. When you set the texture of a sprite, all it does internally is store a pointer to the texture instance. Therefore, if the texture is destroyed or moves elsewhere in memory, the sprite ends up with an invalid texture pointer.

    You must correctly manage the lifetime of your textures and make sure that they live as long as they are used by any sprite.

    you should store your sf::Texture t as a member of your class for it to have the same lifetime as your sprite, and your sprite won't be trying to draw a destroyed texture.