SFML community forums

Help => Graphics => Topic started by: coolhome on January 28, 2009, 02:15:47 pm

Title: Image is white ()
Post by: coolhome on January 28, 2009, 02:15:47 pm
ok first just let me dump my code =)

Code: [Select]
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
Quote
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]
Title: Image is white ()
Post by: Laurent on January 28, 2009, 02:30:04 pm
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.
Title: Image is white ()
Post by: coolhome on January 28, 2009, 02:33:20 pm
Nevermind you can close topic I already solved it I got it...

Code: [Select]
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!
Title: Image is white ()
Post by: Tank on January 28, 2009, 03:41:48 pm
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:
Quote
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.
Title: Image is white ()
Post by: coolhome on February 01, 2009, 11:49:27 pm
so im back and this is what i got :P

ImageManager.hpp
Code: [Select]
#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
Code: [Select]
#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:
Code: [Select]
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
Title: Image is white ()
Post by: Nexus on February 02, 2009, 02:28:12 am
Quote from: "coolhome"
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. ;)
Code: [Select]
sf::Image& ImageManager::Get(const std::string &Key);
Title: Image is white ()
Post by: coolhome on February 02, 2009, 03:00:23 am
Quote from: "Nexus"
Quote from: "coolhome"
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. ;)
Code: [Select]
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
Title: Image is white ()
Post by: Laurent on February 02, 2009, 07:46:17 am
Quote
Just return a reference instead of a pointer.

Then you'll have to use exceptions to handle errors, or return a dummy image.