SFML community forums

Help => Graphics => Topic started by: kanbaru on March 16, 2019, 01:31:17 pm

Title: Load a white rectangle using Game headerfile
Post by: kanbaru on March 16, 2019, 01:31:17 pm
I followed the book SFML Game Development, and find problem in doing the chapter 2, about resources management.

Here I used:
 
#include "Game.h"
#include <SFML/Graphics.hpp>
void main()
{
        Game game;
        game.run();
}
 
While in the loading function, it turns out rendering a white rectangle.

Game.h
#pragma oncE
#include <SFML/Graphics.hpp>
#include <ResourceHolder.hpp>
#include <iostream>
#include <assert.h>

class Game
{
public:
        Game();
        ~Game();
        void run();
private:
        void processEvents();
        void update(sf::Time deltaTime);
        void render();
        void handlePlayerInput(sf::Keyboard::Key key, bool isPressed);
private:
        sf::Sprite player;
        sf::RenderWindow window;
        sf::Texture playerTexture;
        bool pIsMovingUp= false;
        bool pIsMovingDown = false;
        bool pIsMovingLeft = false;
        bool pIsMovingRight = false;
};
 

Game.cpp
Game::Game()
        : window(sf::VideoMode(800, 600), "Simulator", sf::Style::Default)
        , player()
{
        // window.setFramerateLimit(25);
        //Try to load resources
        ResourceHolder<sf::Texture, Textures::ID> textures;
        try
        {
                textures.load(Textures::MainRole, "Media/textures/a.png");
        }
        catch (std::runtime_error& e)
        {
                std::cout << "Exception: " << e.what() << std::endl;
        }
       
        player.setOrigin(100.0f, 100.0f);
        player.setPosition(400.0f, 300.0f);
        player.setTexture(textures.get(Textures::MainRole));
       
}
 

If I use Game class to run the program, a white rectangle will be the result.
However, when I copy the source code from the book's github, it is OK. And the source code is using main.cpp to run the whole program. Here's the github link.
https://github.com/SFML/SFML-Game-Development-Book/tree/master/02_Resources (https://github.com/SFML/SFML-Game-Development-Book/tree/master/02_Resources)
Title: Re: Load a white rectangle using Game headerfile
Post by: Laurent on March 16, 2019, 05:05:34 pm
Your ResourceHolder is local to the Game constructor, and is destroyed when it returns.
Title: Re: Load a white rectangle using Game headerfile
Post by: eXpl0it3r on March 16, 2019, 05:09:37 pm
I hope you're also reading the book and are not just copying code, because I'm pretty sure the book explains why you need a resource holder in the first place.
Once you understand why that is needed, you'd also understand why your code defeats the whole point of it. ;)

You create a resource holder instance that is local to the Game() constructor. So right after the texture is loaded, the resource holder is destroyed again and with it, the texture is destroyed and thus the sprite's reference to the texture is broken and renders a white square.

See also the White Square Problem described in the official tutorial: https://www.sfml-dev.org/tutorials/2.5/graphics-sprite.php#the-white-square-problem

Please make use of the edit function next time, instead of adding a new post every few minutes. :)
Title: Re: Load a white rectangle using Game headerfile
Post by: kanbaru on March 17, 2019, 03:50:11 am
Thanks a lot for all the replies.
I am sorry that I post a trivial question, I am new to SFML. Next time, I will pay attention to the format and official document.
I solved this problem by adding static to the ResourceHolder:
static ResourceHolder<sf::Texture, Textures::ID> textures;
Anyway, thanks for your help.
Title: Re: Load a white rectangle using Game headerfile
Post by: eXpl0it3r on March 17, 2019, 01:59:59 pm
It's fine to ask questions, I merely wanted to point out that the code and book sections you're looking at were written to solve this exact issue. Not realizing this, makes it seem like you haven't understood the concept behind and may want to go back to understand it before moving on. ;)

Adding static "solves" the issue, but it would be better if you used the resource holder as class member.