Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: sf::Texture and sf::Text colliding?  (Read 2752 times)

0 Members and 1 Guest are viewing this topic.

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
sf::Texture and sf::Text colliding?
« on: February 08, 2016, 12:35:30 am »
Hi all,

I had a working project that was about 4000 lines of code, already using many sf::Texture and sf::Text objects. Then I decided that I need a texture manager to optimize loading many files. Here is the code:

//Declarations

class Manager
{
private:
    static map<string, Texture > textures;
public:
    static Texture & add(const string & name, const string & directory);
    static Texture & resolve(const string & name);
};

//Definitions

Texture & Manager::add(const string & name, const string & directory)
{
    // Check, whether a said texture was already maped
    map<string, Texture>::const_iterator it = textures.find(name);
    if (it != textures.end())
    {
        cout << "Said element was loaded" << endl;
        return textures.at(name);
    }

    // Adding a new texture
    Texture tex;
    tex.loadFromFile(directory);
    textures[name] = tex;

    cout << "Texture added" << endl;
    return textures.at(name);
}

Texture & Manager::resolve(const string & name)
{
    cout << "Resolved" << endl;
    return textures.at(name);
}

map<string, Texture > Manager::textures;
 

And I wanted to test it so I replaced this:

void Engine::set_up(int & lvl)
{
    Texture texture;
    texture.loadFromFile("data/loading_screen.png");
    Sprite spr;
    spr.setTexture(texture);

    // ...
}
 

with this:

void Engine::set_up(int & lvl)
{
    srm::Manager::add("Loading screen", "data/loading_screen.png");

    Sprite spr;
    spr.setTexture(srm::Manager::resolve("Loading screen"));

    // ...
}
 

What happened: this is the loading screen. So I pressed "PLAY". Everythink worked, the loading screen appeard, level has been loaded. I got back to main menu and pressed "PLAY" again. And now, for some reason, I get Runtime Library Error: http://ifotos.pl/z/sexsqph. I tought it is caused by new code. But when I tried to debug, it turned out that my game stops on setting sf::Text objects. Random one, to be precised, in random method, some times in the Engine::set_up() method, sometime in other methods. And I am confused. It looks that these are colliding.

What's more, when I moved srm::Manager::add() calling to the constructor of Engine class, everything works fine again
(it looks like this):
//Constructor
Engine(){ srm::Manager::add("Loading screen", "data/loading_screen.png"); }

//Method
void Engine::set_up(int & lvl)
{    
    Sprite spr;
    spr.setTexture(srm::Manager::resolve("Loading screen"));

    // ...
}
 


So can you explain me, whats going on in my project? I don't understand why it's behaving like this? How can I improve my code to make it working perfectly? Thank you in advance!
« Last Edit: February 08, 2016, 12:52:05 am by Skorpion »

DarkRoku12

  • Full Member
  • ***
  • Posts: 203
  • Lua coder.
    • View Profile
    • Email
Re: sf::Texture and sf::Text colliding?
« Reply #1 on: February 08, 2016, 06:55:36 am »
Hi all,

I had a working project that was about 4000 lines of code, already using many sf::Texture and sf::Text objects. Then I decided that I need a texture manager to optimize loading many files. Here is the code:

//Declarations

    static map<string, Texture > textures;

 

The problem is because the memory location.
Cause map order the keys/values pair, this action change its memory adress. You should use a map of pointers. Remeber that sf::Sprite don't copy the texture, but its holds the direction of the texture.

And better use unordered_map is the order dosen't matter to you. unordered_map has better performance over map.

Remember to free (delete) the pointers when you are done with the textures.
I would like a spanish/latin community...
Problems building for Android? Look here

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: sf::Texture and sf::Text colliding?
« Reply #2 on: February 08, 2016, 08:04:54 am »
Quote from: Skorpion
Remember to free (delete) the pointers when you are done with the textures.
[/quote
or just use smart pointers.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: sf::Texture and sf::Text colliding?
« Reply #3 on: February 08, 2016, 01:11:18 pm »
Cause map order the keys/values pair, this action change its memory adress. You should use a map of pointers.
That's wrong. All associative C++ standard containers are stable, the fact that some are ordered has no effect.

The only thing that should be taken care of is that the texture is constructed in-place (or default-constructed and loaded), not copied into the map.

And better use unordered_map is the order dosen't matter to you. unordered_map has better performance over map.
Without further relativation, this is wrong as well. Hash maps provide faster lookup, but you need a certain size before this pays off. Keep in mind that hash maps typically waste a lot of memory, and they also need a good hash function to work (i.e. std::hash + operator== for the stored type).

Then I decided that I need a texture manager to optimize loading many files. Here is the code:
You could use the thor::ResourceHolder class template that I've written. It works for all resources, not just textures, and has some nice extra features (like automatically resolving duplicates, or different lifetime/ownership strategies).
« Last Edit: February 08, 2016, 01:13:29 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: sf::Texture and sf::Text colliding?
« Reply #4 on: February 09, 2016, 12:14:26 am »
Well, thank you all for responses.

Nexus, I've heard of thor, however my team don't want to learn it, so I stuck and I tried to make my own texture manager (SoundBuffer and maybe Text managers were also planned) but I got that runtime error and it stopped me for a while.

I'll give my Manager a few more chances, changing some other parts of code and probably, if it doesn't help, use thor.

There is still a mystery, why method, that should have no real impact on any Text object, causes a bug but moving it to the constructor makes the code work again :) Solve this, if you can, I have no idea, what is going on there ;)
« Last Edit: February 09, 2016, 12:33:18 am by Skorpion »

Skorpion

  • Newbie
  • *
  • Posts: 28
    • View Profile
Re: sf::Texture and sf::Text colliding?
« Reply #5 on: February 09, 2016, 08:51:59 pm »
Ok, I worked on my code and figured out, where EXACTLY the error occures. Forget, please, about those sf::Text objects, most of them, if now all, are innocent. The problem lays in that code:

void Engine::load(int & lvl)
{
        EnterCriticalSection(&critical_section);
        loaded = 0;     // an integer variable incremented after every call
        LeaveCriticalSection(&critical_section);

        load_voices();
        EnterCriticalSection(&critical_section);
        loaded++;
        LeaveCriticalSection(&critical_section);

        load_textures();
        EnterCriticalSection(&critical_section);
        loaded++;
        LeaveCriticalSection(&critical_section);

        //so on
}

void Engine::set_up(int & lvl)
{
        if (!InitializeCriticalSectionAndSpinCount( & critical_section, 0x00000400))
                return;

        thread loading_thread(&Engine::load, this, lvl);

        srm::Manager::add("Loading screen", "loading_screen.png");

        Sprite spr;
        spr.setTexture(srm::Manager::resolve("Loading screen"));

        Text procent;
        procent.setFont(Texts::menu_font);
        EnterCriticalSection(&critical_section);
        procent.setString(loaded);
        LeaveCriticalSection(&critical_section);
        procent.setPosition(200, 200);
        procent.setColor(Color::Blue);
        procent.setCharacterSize(20);

        while (!thread)         //indicates, whether loading_thread still works
        {
                Event events;
                Vector2f mouse(Mouse::getPosition(window));
                while (window.pollEvent(envents))
                {
                        if (events.type == Event::Resized)
                                window.setSize(window_resolution);
                }

                EnterCriticalSection(&critical_section);
                procent.setString(loaded);
                LeaveCriticalSection(&critical_section);

                window.clear();
                window.draw(spr);
                window.draw(procent);   //this causes the error I get
                window.display();
        }
        loading_thread.join();

        DeleteCriticalSection( & sekcja_krytyczna);
}
 

So basicly when I comment out that line, that causes the Runtime Error it doesn't appear. I'll say it again: first attempt to call method Engine::set_up() is always succesful, second attempt always causes an app crash. Can you solve it?

DarkRoku12

  • Full Member
  • ***
  • Posts: 203
  • Lua coder.
    • View Profile
    • Email
Re: sf::Texture and sf::Text colliding?
« Reply #6 on: February 10, 2016, 03:06:12 am »
Quote
Ok, I worked on my code and figured out, where EXACTLY the error occures. Forget, please, about those sf::Text objects, most of them, if now all, are innocent. The problem lays in that code:

void Engine::load(int & lvl)
{
        EnterCriticalSection(&critical_section);
        loaded = 0;     // an integer variable incremented after every call
        LeaveCriticalSection(&critical_section);

        load_voices();
        EnterCriticalSection(&critical_section);
        loaded++;
        LeaveCriticalSection(&critical_section);

        load_textures();
        EnterCriticalSection(&critical_section);
        loaded++;
        LeaveCriticalSection(&critical_section);

        //so on
}
 

What is the point of this function:
LeaveCriticalSection(&critical_section);
what does?... Investigating, seems to be a Windows´ (VS) specific function.

Attach the full code, so maybe somebody who has VS can take the time to debug it.

And check if you use share the same asset manager between threads. if yes, you must make it thread safe using: Semaphores, mutex, or atomic members.

Remeber to handle the events inside the thread that the windows was created.

And try to see if you really needs to use threads. If you need cooperative ( Non-preemptive ) processing you could implement coroutines. In c++ (i'm not a fan of boost but) you have coroutines from boost.
« Last Edit: February 10, 2016, 03:11:00 am by DarkRoku »
I would like a spanish/latin community...
Problems building for Android? Look here