Laurent en parle dans un de ses tutoriels, un bon moteur se devrait de gérer la création des images grâce à une classe, afin notamment d'éviter d'avoir une même image en double dans la mémoire.
Voici donc la classe ImageManager que j'ai créée sur ce principe :
#ifndef h__imagemanager_hpp__ #define h__imagemanager_hpp__ /* * Class ImageManager * Manage sf::Image creation for better use of memory * @author : Adrian Gaudebert - adrian.gaudebert@gmail.com */ class ImageManager { private: std::map<std::string, sf::Image*> Images; /** * Search an Image in memory * @param ImageLink File name of the image * @param ImgTemp Output pointer to the sf::Image if found * @return Boolean, true if the sf::Image is found, false otherwise */ bool SearchImage(const std::string &ImageLink, sf::Image* &ImgTemp); /** * Create a sf::Image from his file name * @param ImageLink File name of the image * @return Pointer to the sf::Image created, or NULL if failed */ sf::Image *CreateImage(const std::string &ImageLink); public: /** * ImageManager constructor */ ImageManager(); /** * ImageManager destructor */ ~ImageManager(); /** * Get a sf::Image from a file name * @param ImageLink File name of the image * @return Pointer to the sf::Image */ sf::Image *GetImage(const std::string &ImageLink); /** * Delete a sf::Image if already loaded * @param Img The sf::Image to destroy * @return None */ void DeleteImage(sf::Image &Img); /** * Delete a sf::Image if already loaded * @param ImageLink File name of the image to destroy * @return None */ void DeleteImage(const std::string& ImageLink); }; #endif /* h__imagemanager_hpp__ */
/* * Class ImageManager * Manage sf::Image creation for better use of memory * @author : Adrian Gaudebert - adrian.gaudebert@gmail.com */ #include "ImageManager.hpp" /* -------------------------- */ /* ImageManager::ImageManager */ /* -------------------------- */ ImageManager::ImageManager() { } /* --------------------------- */ /* ImageManager::~ImageManager */ /* --------------------------- */ ImageManager::~ImageManager() { //On détruit toutes les images restantes std::map<std::string, sf::Image*>::iterator it; for(it = Images.begin(); it != Images.end(); it++) { delete it->second; } } /* ------------------------- */ /* ImageManager::SearchImage */ /* ------------------------- */ bool ImageManager::SearchImage(const std::string &ImageLink, sf::Image* &ImgTemp) { std::map<std::string, sf::Image*>::iterator it; it = Images.find(ImageLink); if(it == Images.end()) { return false; } else { ImgTemp = it->second; } return true; } /* ------------------------- */ /* ImageManager::CreateImage */ /* ------------------------- */ sf::Image *ImageManager::CreateImage(const std::string &ImageLink) { sf::Image *ImgTemp = new sf::Image(); if(ImgTemp->LoadFromFile(ImageLink)) { Images.insert(std::make_pair(ImageLink, ImgTemp)); return ImgTemp; } else { delete ImgTemp; } return NULL; } /* ---------------------- */ /* ImageManager::GetImage */ /* ---------------------- */ sf::Image *ImageManager::GetImage(const std::string &ImageLink) { sf::Image *ImgTemp; //Si l'image demandée n'existe pas déjà, on la créée if(!SearchImage(ImageLink, ImgTemp)) { ImgTemp = CreateImage(ImageLink); } return ImgTemp; } /* ------------------------- */ /* ImageManager::DeleteImage */ /* ------------------------- */ void ImageManager::DeleteImage(sf::Image &Img) { std::map<std::string, sf::Image*>::iterator it; //On cherche l'image demandée for(it = Images.begin(); it != Images.end(); it++) { //Si on la trouve, on la détruit et on la retire if(it->second == &Img) { delete &Img; Images.erase(it); break; } } } /* ------------------------- */ /* ImageManager::DeleteImage */ /* ------------------------- */ void ImageManager::DeleteImage(const std::string& ImageLink) { std::map<std::string, sf::Image*>::iterator it; it = Images.find(ImageLink); if(it != Images.end()) { if(it->second != NULL) { delete (it->second); Images.erase(it); } } }
Vous pouvez télécharger directement les fichiers de cette classe :
Cette classe est normalement un singleton, mais par souci de compatibilité, j'ai choisi de vous laisser le soin d'implémenter le passage de la classe en singleton.
Il est à noter qu'ici, les sf::Image sont indexés en fonction du lien passé en paramètre à la méthode GetImage. Or ce n'est pas forcément la meilleure façon de s'assurer que les doublons sont évités (plusieurs liens différents peuvent mener vers la même image). C'est une méthode simple, et efficace si les liens vers les fichiers sont bien uniformisés dans votre programme, mais elle peut tout de même comporter des défauts dans certains cas.
Si vous avez des commentaires à faire sur cette classe, notamment au niveau des performances, je vous saurais gré de bien vouloir me les envoyer par mail à adrian.gaudebert@gmail.com, ou bien de m'en faire part sur le forum ( Warshadow ).
Merci à Hiura pour ses conseils, qui ont par ailleurs amené quelques légères modifications dans ce code… ;) Merci à zebra22 pour la correction d'une erreur. Merci à bluelink et Orwel pour la correction d'un bug lors de la destruction du Manager.