I'm making a small game using SFML 2.2
I'll start with my code. As I already had about 4000 lines of working code I made a texture manager for storing all textures that are used at a time. I used texures earlier of course but I needed a way to manage them. It looks like this:
//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;
As you can see I have a global map accesed by two methods. Both methods return a reference to a certain texture. So as my project had already quiet a lot of textures I decided to check if my manager works fine and replaced loading one texture with method add and binding it to sprite with resolve. As I compiled code and run it everything worked good untill I went back to menu of my game and decided to "play again". Now, when it came to load the texture again, method add correctly recognized name (key) as already used and method resolve returned correctly texture. At least "Resolved" appeared on the screen. And this is the point when error ocures.
But when I moved calling add from method, where the texture is used to the constructor of the class that uses it, it works fine again. And it's called the same amount of times; once per "play game".
Here is the not working code:
void Engine::set_up(int & lvl)
{
srm::Manager::add("Loading screen", "data/loading_screen.png");
Sprite spr;
spr.setTexture(srm::Manager::resolve("Loading screen"));
// ...
}
Also not working code:
void Engine::set_up(int & lvl)
{
Sprite spr;
spr.setTexture(srm::Manager::add("Loading screen", "data/loading_screen.png");
// ...
}
And working:
//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"));
// ...
}
I feel I made a mistake in my Manager. Here is what the error says:
Microsoft Visual C++ Runtime Library - Error
There is used word "heap" so it just confirmed me that those error is related to my Manager. I made a research in the web and I have found this:
Debug Assertion Failed: _CrtIsValidHeapPointer(pUserData)
I understand what cause the error but I can't understand where my mistake is. The weirdest thing is that those calling add in constructor works and calling it elsewhere doesn't!
I'm sorry if something isn't clear, I'll answer your questions then.
Does anybody know any solution to this issue? Can you explain me, what's wrong in my code? Thank you in advance!
EDIT
Ok, I tracked stack in debug mode and found the culprit. These are sf::Text objects which have in field value
Information not avaliable, no symbols loaded for sfml-graphics-d-2.dll
and in every test it appears in other Text object. Always there are problems with strings, it's always "Unable to read memory" in string parts of my texts. I don't know why, for me it's not even related to my problem. However, when I changed my code back to this:
void Engine::set_up(int & lvl)
{
//srm::Manager::add("Loading screen", "data/loading_screen.png");
Texture texture;
texture.loadFromFile("data/loading_screen.png");
Sprite spr;
spr.setTexture(texture);
//spr.setTexture(srm::Pojemnik::zwroc("Ekran wczytywania"));
so a classic local sf::Texture
object and binding it to sprite, everything works perfectly with no problem.
So as I said, when I put
srm::Manager::add("Loading screen", "data/loading_screen.png");
to the constructor or when I don't use my Manager class at all everything works, when I want to use my code - it hangs.