diff --git a/include/level.hpp b/include/level.hpp index d69cd4f..18e8179 100644 --- a/include/level.hpp +++ b/include/level.hpp @@ -59,14 +59,14 @@ public: virtual ~Level(); /** - * Charge un niveau de jeu depuis le fichier donné + * Charge un niveau de jeu avec le nom donné */ - virtual void load(std::ifstream& file); + virtual void load(std::string name); /** - * Sauvegarde la configuration actuelle comme un niveau + * Sauvegarde la configuration actuelle dans le niveau donné */ - virtual void save(); + virtual void save(std::string name); /** * Appelé par le manager lorsque l'état commence à être utilisé diff --git a/include/resource_manager.hpp b/include/resource_manager.hpp index bf705c9..e7020cc 100644 --- a/include/resource_manager.hpp +++ b/include/resource_manager.hpp @@ -3,13 +3,22 @@ #include #include -#include +#include #include +#include +#include + +typedef std::unique_ptr LevelReader; +typedef std::unique_ptr LevelWriter; class ResourceManager { private: - std::map textures; - std::map fonts; + std::string resources_dir; + + std::unordered_map textures; + std::unordered_map fonts; + + float music_volume; sf::Music music; public: @@ -31,25 +40,36 @@ public: sf::Font& getFont(std::string name); /** - * Change la musique en lecture de fond - * Doit être utilisé pour la lecture en continu + * Récupère un lecteur de fichier vers le niveau donné + * (penser à refermer après usage) */ - void setMusic(std::string name); + LevelReader getLevelReader(std::string name); /** - * Démarre la musique de fond + * Récupère un jacob de fichier vers le niveau donné + * (penser à refermer après usage) */ - void playMusic(); + LevelWriter getLevelWriter(std::string name); /** - * Met en pause la musique de fond + * Démarre la musique de fond donnée */ - void pauseMusic(); + void playMusic(std::string name); /** * Arrête la musique de fond */ void stopMusic(); + + /** + * Récupère le volume de la musique de fond + */ + float getMusicVolume(); + + /** + * Modifie le volume de la musique de fond + */ + void setMusicVolume(float set_music_volume); }; #endif diff --git a/res/monoid.ttf b/res/fonts/monoid.ttf similarity index 100% rename from res/monoid.ttf rename to res/fonts/monoid.ttf diff --git a/res/raleway.ttf b/res/fonts/raleway.ttf similarity index 100% rename from res/raleway.ttf rename to res/fonts/raleway.ttf diff --git a/levels/level1.dat b/res/levels/level1.dat similarity index 100% rename from levels/level1.dat rename to res/levels/level1.dat diff --git a/res/musics/editor.ogg b/res/musics/editor.ogg new file mode 100644 index 0000000..47162fa Binary files /dev/null and b/res/musics/editor.ogg differ diff --git a/res/level1.wav b/res/musics/level1.wav similarity index 100% rename from res/level1.wav rename to res/musics/level1.wav diff --git a/res/level4.ogg b/res/musics/level4.ogg similarity index 100% rename from res/level4.ogg rename to res/musics/level4.ogg diff --git a/res/menu.ogg b/res/musics/menu.ogg similarity index 100% rename from res/menu.ogg rename to res/musics/menu.ogg diff --git a/res/background.tga b/res/textures/background.tga similarity index 100% rename from res/background.tga rename to res/textures/background.tga diff --git a/res/block.tga b/res/textures/block.tga similarity index 100% rename from res/block.tga rename to res/textures/block.tga diff --git a/res/block_select.png b/res/textures/block_select.png similarity index 100% rename from res/block_select.png rename to res/textures/block_select.png diff --git a/res/gravity_block_east.tga b/res/textures/gravity_block_east.tga similarity index 100% rename from res/gravity_block_east.tga rename to res/textures/gravity_block_east.tga diff --git a/res/gravity_block_north.tga b/res/textures/gravity_block_north.tga similarity index 100% rename from res/gravity_block_north.tga rename to res/textures/gravity_block_north.tga diff --git a/res/gravity_block_south.tga b/res/textures/gravity_block_south.tga similarity index 100% rename from res/gravity_block_south.tga rename to res/textures/gravity_block_south.tga diff --git a/res/gravity_block_west.tga b/res/textures/gravity_block_west.tga similarity index 100% rename from res/gravity_block_west.tga rename to res/textures/gravity_block_west.tga diff --git a/res/player.tga b/res/textures/player.tga similarity index 100% rename from res/player.tga rename to res/textures/player.tga diff --git a/src/editor.cpp b/src/editor.cpp index 5a5df52..1821367 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -34,6 +34,8 @@ Editor::~Editor() {} void Editor::begin() { Level::begin(); + + getResourceManager().playMusic("editor.ogg"); getWindow().setFramerateLimit(60); } diff --git a/src/level.cpp b/src/level.cpp index e8b5149..18aa0f4 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -34,18 +34,17 @@ Level::Level(Manager& manager) : State(manager), camera_angle(180.f), gravity_direction(GravityDirection::SOUTH) {} Level::~Level() {} -void Level::load(std::ifstream& file) { - // vide le niveau précédent s'il y a lieu - if (objects.size() != 0) { - objects.clear(); - } +void Level::load(std::string name) { + LevelReader file = getResourceManager().getLevelReader(name); - // positionnement de la caméra au centre du niveau + // vidage du niveau précédent et positionnement + // de la caméra au centre du niveau + objects.clear(); camera.setCenter(0, 0); // lecture de la signture du fichier ("BAR") char signature[3]; - file.read(signature, sizeof(signature)); + file->read(signature, sizeof(signature)); if (strncmp(signature, "BAR", sizeof(signature)) != 0) { throw std::runtime_error( @@ -55,7 +54,7 @@ void Level::load(std::ifstream& file) { // lecture de la version du fichier char file_version; - file.read(&file_version, 1); + file->read(&file_version, 1); if (file_version != 0) { throw std::runtime_error( @@ -65,23 +64,23 @@ void Level::load(std::ifstream& file) { // lecture du nom du niveau std::string std_name; - std::getline(file, std_name, '\0'); + std::getline(*file, std_name, '\0'); name = sf::String(std_name); // lecture du temps total du niveau - file.read(reinterpret_cast(&total_time), sizeof(total_time)); + file->read(reinterpret_cast(&total_time), sizeof(total_time)); total_time = ntohl(total_time); // lecture de la zone de jeu char control_points; - file.read(&control_points, 1); + file->read(&control_points, 1); zone.clear(); for (int i = 0; i < control_points; i++) { float pos_x, pos_y; - file.read(reinterpret_cast(&pos_x), sizeof(pos_x)); - file.read(reinterpret_cast(&pos_y), sizeof(pos_y)); + file->read(reinterpret_cast(&pos_x), sizeof(pos_x)); + file->read(reinterpret_cast(&pos_y), sizeof(pos_y)); pos_x *= Constants::GRID; pos_y *= Constants::GRID; @@ -92,19 +91,19 @@ void Level::load(std::ifstream& file) { // lecture des chemins de la musique et du fond std::string background_name; - std::getline(file, music_name, '\0'); - std::getline(file, background_name, '\0'); + std::getline(*file, music_name, '\0'); + std::getline(*file, background_name, '\0'); background.setTexture(getResourceManager().getTexture(background_name)); // lecture du nombre de blocs int block_count; - file.read(reinterpret_cast(&block_count), sizeof(block_count)); + file->read(reinterpret_cast(&block_count), sizeof(block_count)); block_count = ntohl(block_count); for (int i = 0; i < block_count; i++) { char block_type; - file.read(&block_type, 1); + file->read(&block_type, 1); // vérifie que le type est pris en charge // pour éviter une erreur de segmentation @@ -114,25 +113,28 @@ void Level::load(std::ifstream& file) { ); } - objects.push_back(object_type_map[block_type](file)); + objects.push_back(object_type_map[block_type](*file)); } + + file->close(); } -void Level::save() { +void Level::save(std::string name) { + LevelWriter file = getResourceManager().getLevelWriter(name); + // TODO: faire une fonction d'enregistrement + + file->close(); } void Level::begin() { - ResourceManager& resources = getResourceManager(); - camera = getWindow().getDefaultView(); camera.setCenter(0, 0); if (music_name != "") { - resources.setMusic(music_name); - resources.playMusic(); + getResourceManager().playMusic(music_name); } else { - resources.stopMusic(); + getResourceManager().stopMusic(); } } diff --git a/src/manager.cpp b/src/manager.cpp index f298f18..caad933 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -2,7 +2,7 @@ Manager::Manager() : window( sf::VideoMode(704, 480), "Skizzle", sf::Style::Default, - sf::ContextSettings(0, 0, 2) + sf::ContextSettings(0, 0, 4) ), default_view(window.getDefaultView()), title(sf::String(L"")), state(NULL), next_state(NULL), running(false) {} diff --git a/src/menu.cpp b/src/menu.cpp index 19b7e10..c2253fd 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -9,12 +9,9 @@ Menu::Menu(Manager& manager) : State(manager) {} Menu::~Menu() {} void Menu::begin() { - ResourceManager& resources = getResourceManager(); - loadMainMenu(); - resources.setMusic("menu.wav"); - resources.playMusic(); + getResourceManager().playMusic("menu.ogg"); getWindow().setFramerateLimit(60); } @@ -22,7 +19,7 @@ void Menu::frame(const std::vector& events) { // traitement des événements State::frame(events); - // titre de la fenêtitre + // titre de la fenêtre getManager().setTitle(""); // affichage du menu @@ -170,13 +167,7 @@ void Menu::launchEditor() { void Menu::launchGame(std::string name) { std::shared_ptr game = std::shared_ptr(new Game(getManager())); - std::string path = "./levels/" + name; - - std::ifstream file; - file.open(path, std::ios::binary | std::ios::in); - game->load(file); - file.close(); - + game->load(name); getManager().setState(game); } diff --git a/src/resource_manager.cpp b/src/resource_manager.cpp index 98db13c..b405beb 100644 --- a/src/resource_manager.cpp +++ b/src/resource_manager.cpp @@ -1,20 +1,18 @@ #include "resource_manager.hpp" #include "whereami.h" -#include +#include -ResourceManager::ResourceManager() { - music.setLoop(true); -} +// 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() { - textures.clear(); -} - -/** - * Récupère le chemin actuel de l'exécutable sous la forme - * d'une chaîne de caractères grâce à la librairie whereami - */ -std::string getCurrentDirectory() { +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 buffer = std::unique_ptr(new char[length + 1]); wai_getExecutablePath(buffer.get(), length, &dirname_length); @@ -24,19 +22,17 @@ std::string getCurrentDirectory() { } buffer.get()[length] = '\0'; - return std::string(buffer.get()).substr(0, dirname_length); + std::string base_dir = std::string(buffer.get()).substr(0, dirname_length); + resources_dir = base_dir + SEP + "res" + SEP; + + // initialisation de la musique en bouclage et au volume par défaut + music.setLoop(true); + music.setVolume(music_volume); } -/** - * Récupère le chemin absolu vers la ressource dont - * le nom est passé en argument - */ -inline std::string getResourcePath(std::string name) { -#ifdef _WIN32 - return getCurrentDirectory() + "\\res\\" + name; -#else - return getCurrentDirectory() + "/res/" + name; -#endif +ResourceManager::~ResourceManager() { + textures.clear(); + fonts.clear(); } sf::Texture& ResourceManager::getTexture(std::string name) { @@ -47,9 +43,11 @@ sf::Texture& ResourceManager::getTexture(std::string name) { sf::Texture texture; - // tente de charger la texture dans le chemin "CWD/res/name" - if (!texture.loadFromFile(getResourcePath(name))) { - throw std::runtime_error("Impossible de charger l'image : " + name); + // tente de charger la texture dans le chemin "res/textures/name.png" + if (!texture.loadFromFile(resources_dir + SEP + "textures" + SEP + name)) { + throw std::runtime_error( + "Impossible de charger l'image \"" + name + "\"" + ); } textures[name] = texture; @@ -64,29 +62,71 @@ sf::Font& ResourceManager::getFont(std::string name) { sf::Font font; - // tente de charger la police dans le chemin "CWD/res/name" - if (!font.loadFromFile(getResourcePath(name))) { - throw std::runtime_error("Impossible de charger la police : " + name); + // tente de charger la police depuis le dossier "res/fonts" + if (!font.loadFromFile(resources_dir + SEP + "fonts" + SEP + name)) { + throw std::runtime_error( + "Impossible de charger la police \"" + name + "\"" + ); } fonts[name] = font; return fonts[name]; } -void ResourceManager::setMusic(std::string name) { - if (!music.openFromFile(getResourcePath(name))) { +LevelReader ResourceManager::getLevelReader(std::string name) { + LevelReader reader = LevelReader(new std::ifstream); + reader->open( + resources_dir + SEP + "levels" + SEP + name, + std::ios::binary | std::ios::in + ); + + // on vérifie que le fichier ait correctement été ouvert en lecture + if (reader->fail()) { + throw std::runtime_error( + "Impossible de charger le niveau \"" + name + "\" " + + "(" + std::string(strerror(errno)) + ")" + ); + } + + return reader; +} + +LevelWriter ResourceManager::getLevelWriter(std::string name) { + LevelWriter writer = LevelWriter(new std::ofstream); + writer->open( + resources_dir + SEP + "levels" + SEP + name, + std::ios::binary | std::ios::in + ); + + // on vérifie que le fichier ait correctement été ouvert en écriture + if (writer->fail()) { + throw std::runtime_error( + "Impossible d'écrire le niveau '" + name + "' " + + "(" + std::string(strerror(errno)) + ")" + ); + } + + return writer; +} + +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); } -} -void ResourceManager::playMusic() { music.play(); } -void ResourceManager::pauseMusic() { - music.pause(); -} - void ResourceManager::stopMusic() { music.stop(); } + +float ResourceManager::getMusicVolume() { + return music_volume; +} + +void ResourceManager::setMusicVolume(float set_music_volume) { + music_volume = set_music_volume; + music.setVolume(music_volume); +}