Préchargement des ressources avant le démarrage du jeu pour
éviter l'erreur type "ne répond pas"
This commit is contained in:
		
							parent
							
								
									13fc2e3b92
								
							
						
					
					
						commit
						6eaa4fb77f
					
				|  | @ -32,8 +32,15 @@ endif() | |||
| # Recherche des librairies | ||||
| set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}" ${CMAKE_MODULE_PATH}) | ||||
| add_executable(ptf ${SOURCES}) | ||||
| 
 | ||||
| find_package(SFML 2 REQUIRED system window graphics network audio) | ||||
| find_package(Boost 1.60.0 COMPONENTS system filesystem) | ||||
| 
 | ||||
| include_directories(${SFML_INCLUDE_DIRS}) | ||||
| include_directories(${Boost_INCLUDE_DIRS}) | ||||
| 
 | ||||
| target_link_libraries(ptf ${SFML_LIBRARIES}) | ||||
| target_link_libraries(ptf ${Boost_LIBRARIES}) | ||||
| 
 | ||||
| # Installation de l'exécutable | ||||
| install(TARGETS ptf DESTINATION bin) | ||||
|  |  | |||
|  | @ -12,13 +12,12 @@ | |||
| class Manager { | ||||
| private: | ||||
|     sf::RenderWindow window; | ||||
|     ResourceManager resource_manager; | ||||
| 
 | ||||
|     sf::Clock clock; | ||||
|     sf::View default_view; | ||||
|     sf::String title; | ||||
| 
 | ||||
|     ResourceManager resource_manager; | ||||
|     std::vector<sf::Event> events; | ||||
| 
 | ||||
|     std::shared_ptr<State> state; | ||||
|     std::shared_ptr<State> next_state; | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| #include <SFML/Audio.hpp> | ||||
| #include <boost/filesystem.hpp> | ||||
| #include <unordered_map> | ||||
| #include <string> | ||||
| #include <fstream> | ||||
|  | @ -16,29 +17,34 @@ | |||
|  */ | ||||
| class ResourceManager { | ||||
| private: | ||||
|     std::string resources_dir; | ||||
|     bool preloaded; | ||||
| 
 | ||||
|     boost::filesystem::path textures_path; | ||||
|     std::unordered_map<std::string, std::unique_ptr<sf::Texture>> textures; | ||||
|     boost::filesystem::path fonts_path; | ||||
|     std::unordered_map<std::string, std::unique_ptr<sf::Font>> fonts; | ||||
| 
 | ||||
|     boost::filesystem::path levels_path; | ||||
| 
 | ||||
|     boost::filesystem::path musics_path; | ||||
|     float music_volume; | ||||
|     sf::Music music; | ||||
| 
 | ||||
| public: | ||||
|     ResourceManager(); | ||||
|     ~ResourceManager(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère une image. Réutilise l'image déjà chargée | ||||
|      * si elle l'a déjà été, sinon, tente de la charger | ||||
|      * depuis son emplacement | ||||
|      * Précharge toutes les ressources préchargeables | ||||
|      */ | ||||
|     void preload(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère une texture préchargée | ||||
|      */ | ||||
|     sf::Texture& getTexture(std::string name); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère la police demandée. Réutilise une police | ||||
|      * déjà chargée si elle a déjà été demandée, sinon, la | ||||
|      * charge depuis son emplacement | ||||
|      * Récupère une police préchargée | ||||
|      */ | ||||
|     sf::Font& getFont(std::string name); | ||||
| 
 | ||||
|  |  | |||
|  | @ -52,6 +52,9 @@ Editor::~Editor() {} | |||
| void Editor::begin() { | ||||
|     Level::begin(); | ||||
| 
 | ||||
|     getResourceManager().stopMusic(); | ||||
|     // TODO: on doit arrêter la musique car celle du
 | ||||
|     // niveau est chargée par dessous dans level.. C'est sale
 | ||||
|     getResourceManager().playMusic("editor.ogg"); | ||||
|     getWindow().setFramerateLimit(Manager::FPS); | ||||
| } | ||||
|  |  | |||
|  | @ -1,13 +1,21 @@ | |||
| #include <iostream> | ||||
| #include "manager.hpp" | ||||
| 
 | ||||
| const unsigned int Manager::FPS = 60; | ||||
| const sf::Time Manager::FRAME_TIME = sf::seconds(1.f / Manager::FPS); | ||||
| 
 | ||||
| Manager::Manager() : window( | ||||
|     sf::VideoMode(704, 480), "Skizzle", sf::Style::Default, | ||||
|     sf::ContextSettings(0, 0, 2) | ||||
| ), default_view(window.getDefaultView()), title(sf::String(L"")), | ||||
| state(NULL), next_state(NULL), running(false) {} | ||||
| Manager::Manager() : default_view(window.getDefaultView()), | ||||
| title(sf::String(L"")), state(NULL), next_state(NULL), running(false) { | ||||
|     // préchargement des textures
 | ||||
|     resource_manager.preload(); | ||||
| 
 | ||||
|     // création de la fenêtre (après avoir préchargé les ressources,
 | ||||
|     // on évite ainsi tout lag pendant le traitement des événements)
 | ||||
|     window.create( | ||||
|         sf::VideoMode(704, 480), "Skizzle", sf::Style::Default, | ||||
|         sf::ContextSettings(0, 0, 2) | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| void Manager::start() { | ||||
|     running = true; | ||||
|  |  | |||
|  | @ -1,86 +1,104 @@ | |||
| #include "resource_manager.hpp" | ||||
| #include "whereami.h" | ||||
| #include <iostream> | ||||
| #include <cstring> | ||||
| 
 | ||||
| // définition du séparateur de fichiers en fonction
 | ||||
| // du type de système
 | ||||
| #ifdef _WIN32 | ||||
| const std::string SEP = "\\"; | ||||
| #else | ||||
| const std::string SEP = "/"; | ||||
| #endif | ||||
| 
 | ||||
| ResourceManager::ResourceManager() : music_volume(5) { | ||||
|     // on récupère le chemin actuel de l'exécutable pour pouvoir accéder
 | ||||
|     // au dossier des ressources qui est situé dans le même dossier
 | ||||
|     int length = wai_getExecutablePath(NULL, 0, NULL), dirname_length; | ||||
|     std::unique_ptr<char[]> buffer = std::unique_ptr<char[]>(new char[length + 1]); | ||||
|     wai_getExecutablePath(buffer.get(), length, &dirname_length); | ||||
| 
 | ||||
|     if (length == 0) { | ||||
|         throw std::runtime_error("Impossible de déterminer le chemin actuel"); | ||||
|     } | ||||
| 
 | ||||
|     buffer.get()[length] = '\0'; | ||||
|     std::string base_dir = std::string(buffer.get()).substr(0, dirname_length); | ||||
|     resources_dir = base_dir + SEP + "res" + SEP; | ||||
| using dir_iter = boost::filesystem::directory_iterator; | ||||
| using fs_path = boost::filesystem::path; | ||||
| 
 | ||||
| ResourceManager::ResourceManager() : preloaded(false), music_volume(20) { | ||||
|     // initialisation de la musique en bouclage et au volume par défaut
 | ||||
|     music.setLoop(true); | ||||
|     music.setVolume(music_volume); | ||||
| } | ||||
| 
 | ||||
| ResourceManager::~ResourceManager() { | ||||
|     textures.clear(); | ||||
|     fonts.clear(); | ||||
| void ResourceManager::preload() { | ||||
|     if (preloaded) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     fs_path current = boost::filesystem::current_path(); | ||||
|     dir_iter end; | ||||
| 
 | ||||
|     // on garde une référence aux chemins des différentes ressources
 | ||||
|     textures_path = current / "res/textures"; | ||||
|     fonts_path = current / "res/fonts"; | ||||
|     levels_path = current / "res/levels"; | ||||
|     musics_path = current / "res/musics"; | ||||
| 
 | ||||
|     // préchargement de toutes les textures
 | ||||
|     for (dir_iter it(textures_path); it != end; ++it) { | ||||
|         if (boost::filesystem::is_regular_file(it->path())) { | ||||
|             std::string full_path = boost::filesystem::canonical(it->path()).string(); | ||||
|             std::string name = it->path().filename().string(); | ||||
| 
 | ||||
|             auto texture = std::unique_ptr<sf::Texture>(new sf::Texture); | ||||
|             std::cout << "Chargement de la texture " << name << "... "; | ||||
| 
 | ||||
|             if (!texture->loadFromFile(full_path)) { | ||||
|                 std::cerr << "ERREUR!" << std::endl; | ||||
|             } else { | ||||
|                 std::cout << "OK!" << std::endl; | ||||
|             } | ||||
| 
 | ||||
|             textures[name] = std::move(texture); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // préchargement de toutes les polices
 | ||||
|     for (dir_iter it(fonts_path); it != end; ++it) { | ||||
|         if (boost::filesystem::is_regular_file(it->path())) { | ||||
|             std::string full_path = boost::filesystem::canonical(it->path()).string(); | ||||
|             std::string name = it->path().filename().string(); | ||||
| 
 | ||||
|             auto font = std::unique_ptr<sf::Font>(new sf::Font); | ||||
|             std::cout << "Chargement de la police " << name << "... "; | ||||
| 
 | ||||
|             if (!font->loadFromFile(full_path)) { | ||||
|                 std::cerr << "ERREUR!" << std::endl; | ||||
|             } else { | ||||
|                 std::cout << "OK!" << std::endl; | ||||
|             } | ||||
| 
 | ||||
|             fonts[name] = std::move(font); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     preloaded = true; | ||||
| } | ||||
| 
 | ||||
| sf::Texture& ResourceManager::getTexture(std::string name) { | ||||
|     // si la texture est déjà chargée, on l'utilise directement
 | ||||
|     if (textures.count(name) > 0) { | ||||
|         return *textures[name]; | ||||
|     } | ||||
| 
 | ||||
|     auto texture = std::unique_ptr<sf::Texture>(new sf::Texture); | ||||
| 
 | ||||
|     // tente de charger la texture dans le chemin "res/textures/name.png"
 | ||||
|     if (!texture->loadFromFile(resources_dir + SEP + "textures" + SEP + name)) { | ||||
|     if (textures.count(name) == 0) { | ||||
|         throw std::runtime_error( | ||||
|             "Impossible de charger l'image \"" + name + "\"" | ||||
|             "Impossible de charger la texture inexistante : " + name | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     textures[name] = std::move(texture); | ||||
|     return *textures[name]; | ||||
| } | ||||
| 
 | ||||
| sf::Font& ResourceManager::getFont(std::string name) { | ||||
|     // si la police est déjà chargée, on l'utilise directement
 | ||||
|     if (fonts.count(name) > 0) { | ||||
|         return *fonts[name]; | ||||
|     } | ||||
| 
 | ||||
|     auto font = std::unique_ptr<sf::Font>(new sf::Font); | ||||
| 
 | ||||
|     // tente de charger la police depuis le dossier "res/fonts"
 | ||||
|     if (!font->loadFromFile(resources_dir + SEP + "fonts" + SEP + name)) { | ||||
|     if (fonts.count(name) == 0) { | ||||
|         throw std::runtime_error( | ||||
|             "Impossible de charger la police \"" + name + "\"" | ||||
|             "Impossible de charger la police inexistante : " + name | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     fonts[name] = std::move(font); | ||||
|     return *fonts[name]; | ||||
| } | ||||
| 
 | ||||
| std::string ResourceManager::getLevelPath(std::string name) { | ||||
|     return resources_dir + SEP + "levels" + SEP + name; | ||||
|     return boost::filesystem::canonical(levels_path / name).string(); | ||||
| } | ||||
| 
 | ||||
| void ResourceManager::playMusic(std::string name) { | ||||
|     // tente de charger la musique depuis le dossier "res/musics"
 | ||||
|     if (!music.openFromFile(resources_dir + SEP + "musics" + SEP + name)) { | ||||
|         throw std::runtime_error("Impossible de charger la musique : " + name); | ||||
|     std::string full_path = boost::filesystem::canonical(musics_path / name).string(); | ||||
|     std::cout << "Lecture de la musique " << name << "... "; | ||||
| 
 | ||||
|     if (!music.openFromFile(full_path)) { | ||||
|         std::cerr << "ERREUR!" << std::endl; | ||||
|     } else { | ||||
|         std::cout << "OK!" << std::endl; | ||||
|     } | ||||
| 
 | ||||
|     music.play(); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue