-
Here's my little resource Manager:
#include <string>
#include <map>
template <typename Resource>
class ResourceManager
{
public:
bool load(std::string address)
{
Resource temporaryResource;
bool success = temporaryResource.loadFromFile(address); // does not handle errors
resourceHolder.insert( {address, temporaryResource} );
return success;
}
Resource* get(std::string ID)
{
return &resourceHolder[ID];
}
private:
std::map <std::string, Resource> resourceHolder;
};
Now I have to use it like this:
ResourceManager <sf::Font> fontmanager;
ResourceManager <sf::Texture> texturemanager;
if (!fontmanager.load("consolas.ttf")) return -1;
if (!texturemanager.load("spritesheet.png")) return -2;
Sf::Sprite sprite(*texturemanager.get("spritesheet.png"));
sf::Text text("string", *fontmanager.get("consolas.ttf"), 24);
window.draw(sprite);
window.draw(text);
Instead I would like to have a single super resource manager that could handle all types of stuff that have loadFromFile function, so I could use it like this:
ResourceManager UltimateResourceManager;
if (!UltimateResourceManager.load("consolas.ttf")) return -1;
if (!UltimateResourceManager.load("spritesheet.png")) return -2;
Sf::Sprite sprite(*UltimateResourceManager.get("spritesheet.png"));
sf::Text text("string", *UltimateResourceManager.get("consolas.ttf"), 24);
window.draw(sprite);
window.draw(text);
I've tried to find a base class in SFML that provides pure virtual loadFromFile function but my search was unsuccessful.
So, is my idea possible, and more importantly, can it be made in easy way?
Oh, and yeah, I know that my resource manager can't delete any resources, but I think that's OK as long as my game doesn't eat more than 100MB RAM, and that's a problem not to worry about for a long time for me :)
-
Totally misread your post - sorry about that. But if you're looking into a universal resource manager that can load any type from SFML, I would look into using generics.
That way, you can write generic code to deal with a multitude of types.
-
Totally misread your post - sorry about that. But if you're looking into a universal resource manager that can load any type from SFML, I would look into using generics.
Thank You for your response! What is a generic? Is it going to be hard to implement one? You know, I'm totally green...
-
im newbie in c++, but may be it will work (it seems to work):
class ResourceManager
{
public:
template<typename Resource>
bool load(std::string address)
{
Resource temporaryResource;
bool success = temporaryResource.loadFromFile(address);
resourceHolder.insert( {address, &temporaryResource} ); // insert pointer instead of value
return success;
}
template<typename Resource>
Resource* get(std::string ID)
{
return static_cast<Resource *>(resourceHolder[ID]);
}
private:
std::map <std::string, void *> resourceHolder; // can store pointer to anything
};
// use
ResourceManager UltimateResourceManager;
if (!UltimateResourceManager.load<sf::Texture>("img.png")) return -2;
sf::Sprite sprite(*UltimateResourceManager.get<sf::Texture>("img.png"));
but if the object dies, pointer to this object still be in resourceHolder
UPD
insert pointer line should be
resourceHolder.insert( {address, static_cast<void *>(&temporaryResource)} );
-
http://en.wikipedia.org/wiki/Template_%28C%2B%2B%29
Take a read up on templates/generics. It allows you essentially to write generic code that can work with many types. So you "hopefully" write once - with a tweak here or there - and then can pass in a multitude of different types.
So for your resource manager, you could build a generic class that handles resources, without having to make specific cases for load, for instance, based on type. It would just be one load, using generics/templates (code-wise)
Before just jumping into code though, I would take the time to read about generics and how to use them effectively.
-
Have you looked at the Thor resources module?
http://www.bromeon.ch/libraries/thor/v2.0/tutorial-resources.html
-
im newbie in c++, but may be it will work (it seems to work):
class ResourceManager
{
public:
template<typename Resource>
bool load(std::string address)
{
Resource temporaryResource;
bool success = temporaryResource.loadFromFile(address);
resourceHolder.insert( {address, &temporaryResource} ); // insert pointer instead of value
return success;
}
template<typename Resource>
Resource* get(std::string ID)
{
return static_cast<Resource *>(resourceHolder[ID]);
}
private:
std::map <std::string, void *> resourceHolder; // can store pointer to anything
};
// use
ResourceManager UltimateResourceManager;
if (!UltimateResourceManager.load<sf::Texture>("img.png")) return -2;
sf::Sprite sprite(*UltimateResourceManager.get<sf::Texture>("img.png"));
but if the object dies, pointer to this object still be in resourceHolder
Brilliant! It compiles, but have you tried actually drawing? Program throws segmentation fault error
-
i've updated my post, may be it helps
but i really have only basic thoughts about how to do this
i'm not cpp programmer, sorry =(
i think object destroyed (cause it on stack) and we need to store it on heap instead of stack (http://www.sfml-dev.org/tutorials/2.0/graphics-sprite.php#the-white-square-problem)
try this, but i'm summon good c++ programmer in this topic)
class ResourceManager
{
public:
template<typename Resource>
bool load(std::string address)
{
auto temporaryResource = new Resource(); // will be in memory until delete ptr
bool success = temporaryResource->loadFromFile(address);
resourceHolder.insert( {address, static_cast<void *>(temporaryResource)} );
return success;
}
template<typename Resource>
Resource* get(std::string ID)
{
return static_cast<Resource *>(resourceHolder[ID]);
}
private:
std::map <std::string, void *> resourceHolder;
};
i've tested drawing, ant it's works fine
-
I would suggest you guys having trouble with generics read over something like this:
http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part
Trying to just throw in generics into a class and seeing if it works, without really understanding the code you're writing is not a good idea.
If you read and understand what and how these work, all of the syntax and how awesome they can be will suddenly make sense. Take the time to learn about them first. Then implementing generics into a simple resource manager won't be very hard.
-
Okay...
After some reading I've discovered that this is an advanced topic and involves more pointers...
After some thinking I've concluded that multiple resource managers add only a couple (<10) additional lines of code.
So here's my solution:
ResourceManager <sf::Font> fontmanager;
ResourceManager <sf::Texture> texturemanager;
ResourceManager <sf::SoundBuffer> buffermanager;
/// and so on...
-
Read about interfaces.
-
Read about interfaces.
I did. I have a GameState interface class that, besides pure public virtual function run() that returns which game state to switch to afterwards, also holds global variables (protected), that can be accessed by all other game states. That is so awesome and made programming really easier for me. Here look at this beauty:
/// This is "GameState.hpp"
/// DEPENDENCIES
#include <SFML/Graphics.hpp>
/// GLOBAL CONSTANTS
const unsigned FLAGS = sf::Style::Close;
const unsigned WIDTH = 640;
const unsigned HEIGHT = 360;
const unsigned FPS = 30;
const std::string TITLE = "LabMouse";
enum ListOfGameStates
{
STATE_MENU,
STATE_EXIT
};
class GameState
{
public:
GameState();
virtual ListOfGameStates run() = 0;
protected:
/// GLOBAL (USED BETWEEN ALL GAME STAGES) VARIABLES
sf::RenderWindow window;
sf::Event event;
sf::Font font; /// TEMPORARY; GONNA BE TURNED INTO FONT RESOURCE MANAGER
bool gotEvent; /// Is true if event queue is not empty
};