SFML community forums
Help => Graphics => Topic started by: coolhome on January 28, 2009, 02:15:47 pm
-
ok first just let me dump my code =)
struct sprite {
sf::Image Image;
sf::Sprite Sprite;
int x;
int y;
float rotation;
sf::IntRect SubRect;
};
typedef std::pair<std::string, sprite> value_type;
std::map<std::string, sprite> sprites;
std::map<std::string, sprite>::iterator spritesIterator;
void loadimage(std::string key, std::string Filename) {
sprite _spriteStruct;
sf::Image _load;
sf::Sprite _sprite;
if(! _load.LoadFromFile(Filename)) {
//error
}
_spriteStruct.Image = _load;
_spriteStruct.Sprite = _sprite;
_spriteStruct.Sprite.SetImage(_spriteStruct.Image);
sprites.insert(std::pair<std::string,sprite>(key,_spriteStruct));
}
Ok well i understand this
You have to be particularly careful when manipulating images. A sf::Image instance is a resource which is slow to load, heavy to copy and uses a lot of memory.
A lot of people, especially beginners, will just put an instance of sf::Image wherever they have an instance of sf::Sprite, because it may seem the simplest way to draw something. The fact is that it's generally a bad idea. The most obvious problem is when copying such objects (just putting them into an array generates copies) : the sprites will most likely appear white. The reason is that a sprite only points to an external image it doesn't own one, so when the image is copied the sprite has to be updated to point to the new copy of the image. This is quite easy to handle, you just have to define a copy constructor for such classes holding (or deriving from) a sprite and an image
but i dont understand exactly what im doing wrong...[/code]
-
The image bound to the sprite will be destroyed right after loadimage returns. You have to make it live at least as long as the sprites uses it.
-
Nevermind you can close topic I already solved it I got it...
struct spriteStruct {
sf::Image Image;
sf::Sprite Sprite;
int x;
int y;
float rotation;
sf::IntRect SubRect;
};
typedef std::pair<std::string, spriteStruct> value_type;
std::map<std::string, spriteStruct> sprites;
std::map<std::string, spriteStruct>::iterator spritesIterator;
void loadimage(std::string key, std::string Filename) {
spriteStruct _spriteStruct;
sprites.insert(std::pair<std::string,spriteStruct>(key,_spriteStruct));
sprites[key].Image.LoadFromFile(Filename);
sprites[key].Sprite.SetImage(sprites[key].Image);
}
EDIT: Thanks for that info and I love SFML a lot more then SDL!
-
But you will begin to hate it when you don't start to optimize your program in a way that it doesn't consume a huge amount of memory. :)
Do I get you right that you're loading an image for *each sprite*?
You said you understood the following paragraph from the SFML tutorials:
A lot of people, especially beginners, will just put an instance of sf::Image wherever they have an instance of sf::Sprite, because it may seem the simplest way to draw something. The fact is that it's generally a bad idea.
But you didn't. :) Please load an image only once. Images can and should be shared between multiple sprites.
-
so im back and this is what i got :P
ImageManager.hpp
#pragma once
#include "Includes.hpp"
class ImageManager {
public:
typedef pair<string, sf::Image*> Images;
typedef map<string, sf::Image*> ImagesMap;
ImagesMap manager;
ImageManager();
~ImageManager();
bool Load(const string &Key, const string &Filename);
sf::Image* Get(const string &Key);
};
and ImageManager.cpp
#include "Includes.hpp"
ImageManager::ImageManager() {
}
ImageManager::~ImageManager() {
while(manager.begin() != manager.end()) {
delete manager.begin()->second;
manager.erase(manager.begin());
}
}
bool ImageManager::Load(const string &Key, const string &Filename) {
sf::Image* image = new sf::Image();
if(! image->LoadFromFile(Filename) ) {
delete image;
image = NULL;
return false;
} else {
manager.insert(Images(Key, image));
return true;
}
}
sf::Image* ImageManager::Get(const string &Key) {
sf::Image *resource = NULL;
ImagesMap::iterator it = manager.find(Key);
if(it != manager.end()) {
resource = it->second;
}
return resource;
}
Example:
ImageManager manager;
sf::Sprite mouse;
if(! manager.Load("mouse", "mouseGraphic.gif")) {
//error here
}
mouse.SetImage(*manager.Get("mouse"));
Do I always need to add the * when setting the image? just wondering if there is a way to remove it... Also the imagemanager class isn't finished yet >.> got some things to add like checking if the key already exists in the map
-
Do I always need to add the * when setting the image? just wondering if there is a way to remove it...
Just return a reference instead of a pointer. ;)
sf::Image& ImageManager::Get(const std::string &Key);
-
Do I always need to add the * when setting the image? just wondering if there is a way to remove it...
Just return a reference instead of a pointer. ;)
sf::Image& ImageManager::Get(const std::string &Key);
wow I feel like a noob now :P
wait I am kind of new to C++ >.< nvm
-
Just return a reference instead of a pointer.
Then you'll have to use exceptions to handle errors, or return a dummy image.