Amélioration interface ResourceManager et réorganisation ressources

This commit is contained in:
Mattéo Delabre 2016-04-09 22:36:07 +02:00
parent 2b177950b4
commit 1bc28ad509
22 changed files with 144 additions and 89 deletions

View File

@ -59,14 +59,14 @@ public:
virtual ~Level(); 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é * Appelé par le manager lorsque l'état commence à être utilisé

View File

@ -3,13 +3,22 @@
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp> #include <SFML/Audio.hpp>
#include <map> #include <unordered_map>
#include <string> #include <string>
#include <fstream>
#include <memory>
typedef std::unique_ptr<std::ifstream> LevelReader;
typedef std::unique_ptr<std::ofstream> LevelWriter;
class ResourceManager { class ResourceManager {
private: private:
std::map<std::string, sf::Texture> textures; std::string resources_dir;
std::map<std::string, sf::Font> fonts;
std::unordered_map<std::string, sf::Texture> textures;
std::unordered_map<std::string, sf::Font> fonts;
float music_volume;
sf::Music music; sf::Music music;
public: public:
@ -31,25 +40,36 @@ public:
sf::Font& getFont(std::string name); sf::Font& getFont(std::string name);
/** /**
* Change la musique en lecture de fond * Récupère un lecteur de fichier vers le niveau donné
* Doit être utilisé pour la lecture en continu * (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 * Arrête la musique de fond
*/ */
void stopMusic(); 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 #endif

BIN
res/musics/editor.ogg Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 764 B

After

Width:  |  Height:  |  Size: 764 B

View File

@ -34,6 +34,8 @@ Editor::~Editor() {}
void Editor::begin() { void Editor::begin() {
Level::begin(); Level::begin();
getResourceManager().playMusic("editor.ogg");
getWindow().setFramerateLimit(60); getWindow().setFramerateLimit(60);
} }

View File

@ -34,18 +34,17 @@ Level::Level(Manager& manager) : State(manager), camera_angle(180.f),
gravity_direction(GravityDirection::SOUTH) {} gravity_direction(GravityDirection::SOUTH) {}
Level::~Level() {} Level::~Level() {}
void Level::load(std::ifstream& file) { void Level::load(std::string name) {
// vide le niveau précédent s'il y a lieu LevelReader file = getResourceManager().getLevelReader(name);
if (objects.size() != 0) {
objects.clear();
}
// 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); camera.setCenter(0, 0);
// lecture de la signture du fichier ("BAR") // lecture de la signture du fichier ("BAR")
char signature[3]; char signature[3];
file.read(signature, sizeof(signature)); file->read(signature, sizeof(signature));
if (strncmp(signature, "BAR", sizeof(signature)) != 0) { if (strncmp(signature, "BAR", sizeof(signature)) != 0) {
throw std::runtime_error( throw std::runtime_error(
@ -55,7 +54,7 @@ void Level::load(std::ifstream& file) {
// lecture de la version du fichier // lecture de la version du fichier
char file_version; char file_version;
file.read(&file_version, 1); file->read(&file_version, 1);
if (file_version != 0) { if (file_version != 0) {
throw std::runtime_error( throw std::runtime_error(
@ -65,23 +64,23 @@ void Level::load(std::ifstream& file) {
// lecture du nom du niveau // lecture du nom du niveau
std::string std_name; std::string std_name;
std::getline(file, std_name, '\0'); std::getline(*file, std_name, '\0');
name = sf::String(std_name); name = sf::String(std_name);
// lecture du temps total du niveau // lecture du temps total du niveau
file.read(reinterpret_cast<char*>(&total_time), sizeof(total_time)); file->read(reinterpret_cast<char*>(&total_time), sizeof(total_time));
total_time = ntohl(total_time); total_time = ntohl(total_time);
// lecture de la zone de jeu // lecture de la zone de jeu
char control_points; char control_points;
file.read(&control_points, 1); file->read(&control_points, 1);
zone.clear(); zone.clear();
for (int i = 0; i < control_points; i++) { for (int i = 0; i < control_points; i++) {
float pos_x, pos_y; float pos_x, pos_y;
file.read(reinterpret_cast<char*>(&pos_x), sizeof(pos_x)); file->read(reinterpret_cast<char*>(&pos_x), sizeof(pos_x));
file.read(reinterpret_cast<char*>(&pos_y), sizeof(pos_y)); file->read(reinterpret_cast<char*>(&pos_y), sizeof(pos_y));
pos_x *= Constants::GRID; pos_x *= Constants::GRID;
pos_y *= 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 // lecture des chemins de la musique et du fond
std::string background_name; std::string background_name;
std::getline(file, music_name, '\0'); std::getline(*file, music_name, '\0');
std::getline(file, background_name, '\0'); std::getline(*file, background_name, '\0');
background.setTexture(getResourceManager().getTexture(background_name)); background.setTexture(getResourceManager().getTexture(background_name));
// lecture du nombre de blocs // lecture du nombre de blocs
int block_count; int block_count;
file.read(reinterpret_cast<char*>(&block_count), sizeof(block_count)); file->read(reinterpret_cast<char*>(&block_count), sizeof(block_count));
block_count = ntohl(block_count); block_count = ntohl(block_count);
for (int i = 0; i < block_count; i++) { for (int i = 0; i < block_count; i++) {
char block_type; char block_type;
file.read(&block_type, 1); file->read(&block_type, 1);
// vérifie que le type est pris en charge // vérifie que le type est pris en charge
// pour éviter une erreur de segmentation // 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 // TODO: faire une fonction d'enregistrement
file->close();
} }
void Level::begin() { void Level::begin() {
ResourceManager& resources = getResourceManager();
camera = getWindow().getDefaultView(); camera = getWindow().getDefaultView();
camera.setCenter(0, 0); camera.setCenter(0, 0);
if (music_name != "") { if (music_name != "") {
resources.setMusic(music_name); getResourceManager().playMusic(music_name);
resources.playMusic();
} else { } else {
resources.stopMusic(); getResourceManager().stopMusic();
} }
} }

View File

@ -2,7 +2,7 @@
Manager::Manager() : window( Manager::Manager() : window(
sf::VideoMode(704, 480), "Skizzle", sf::Style::Default, 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"")), ), default_view(window.getDefaultView()), title(sf::String(L"")),
state(NULL), next_state(NULL), running(false) {} state(NULL), next_state(NULL), running(false) {}

View File

@ -9,12 +9,9 @@ Menu::Menu(Manager& manager) : State(manager) {}
Menu::~Menu() {} Menu::~Menu() {}
void Menu::begin() { void Menu::begin() {
ResourceManager& resources = getResourceManager();
loadMainMenu(); loadMainMenu();
resources.setMusic("menu.wav");
resources.playMusic();
getResourceManager().playMusic("menu.ogg");
getWindow().setFramerateLimit(60); getWindow().setFramerateLimit(60);
} }
@ -22,7 +19,7 @@ void Menu::frame(const std::vector<sf::Event>& events) {
// traitement des événements // traitement des événements
State::frame(events); State::frame(events);
// titre de la fenêtitre // titre de la fenêtre
getManager().setTitle(""); getManager().setTitle("");
// affichage du menu // affichage du menu
@ -170,13 +167,7 @@ void Menu::launchEditor() {
void Menu::launchGame(std::string name) { void Menu::launchGame(std::string name) {
std::shared_ptr<Game> game = std::shared_ptr<Game>(new Game(getManager())); std::shared_ptr<Game> game = std::shared_ptr<Game>(new Game(getManager()));
std::string path = "./levels/" + name; game->load(name);
std::ifstream file;
file.open(path, std::ios::binary | std::ios::in);
game->load(file);
file.close();
getManager().setState(game); getManager().setState(game);
} }

View File

@ -1,20 +1,18 @@
#include "resource_manager.hpp" #include "resource_manager.hpp"
#include "whereami.h" #include "whereami.h"
#include <memory> #include <cstring>
ResourceManager::ResourceManager() { // définition du séparateur de fichiers en fonction
music.setLoop(true); // du type de système
} #ifdef _WIN32
const std::string SEP = "\\";
#else
const std::string SEP = "/";
#endif
ResourceManager::~ResourceManager() { ResourceManager::ResourceManager() : music_volume(5) {
textures.clear(); // 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
/**
* 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() {
int length = wai_getExecutablePath(NULL, 0, NULL), dirname_length; int length = wai_getExecutablePath(NULL, 0, NULL), dirname_length;
std::unique_ptr<char[]> buffer = std::unique_ptr<char[]>(new char[length + 1]); std::unique_ptr<char[]> buffer = std::unique_ptr<char[]>(new char[length + 1]);
wai_getExecutablePath(buffer.get(), length, &dirname_length); wai_getExecutablePath(buffer.get(), length, &dirname_length);
@ -24,19 +22,17 @@ std::string getCurrentDirectory() {
} }
buffer.get()[length] = '\0'; 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);
} }
/** ResourceManager::~ResourceManager() {
* Récupère le chemin absolu vers la ressource dont textures.clear();
* le nom est passé en argument fonts.clear();
*/
inline std::string getResourcePath(std::string name) {
#ifdef _WIN32
return getCurrentDirectory() + "\\res\\" + name;
#else
return getCurrentDirectory() + "/res/" + name;
#endif
} }
sf::Texture& ResourceManager::getTexture(std::string name) { sf::Texture& ResourceManager::getTexture(std::string name) {
@ -47,9 +43,11 @@ sf::Texture& ResourceManager::getTexture(std::string name) {
sf::Texture texture; sf::Texture texture;
// tente de charger la texture dans le chemin "CWD/res/name" // tente de charger la texture dans le chemin "res/textures/name.png"
if (!texture.loadFromFile(getResourcePath(name))) { if (!texture.loadFromFile(resources_dir + SEP + "textures" + SEP + name)) {
throw std::runtime_error("Impossible de charger l'image : " + name); throw std::runtime_error(
"Impossible de charger l'image \"" + name + "\""
);
} }
textures[name] = texture; textures[name] = texture;
@ -64,29 +62,71 @@ sf::Font& ResourceManager::getFont(std::string name) {
sf::Font font; sf::Font font;
// tente de charger la police dans le chemin "CWD/res/name" // tente de charger la police depuis le dossier "res/fonts"
if (!font.loadFromFile(getResourcePath(name))) { if (!font.loadFromFile(resources_dir + SEP + "fonts" + SEP + name)) {
throw std::runtime_error("Impossible de charger la police : " + name); throw std::runtime_error(
"Impossible de charger la police \"" + name + "\""
);
} }
fonts[name] = font; fonts[name] = font;
return fonts[name]; return fonts[name];
} }
void ResourceManager::setMusic(std::string name) { LevelReader ResourceManager::getLevelReader(std::string name) {
if (!music.openFromFile(getResourcePath(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); throw std::runtime_error("Impossible de charger la musique : " + name);
} }
}
void ResourceManager::playMusic() {
music.play(); music.play();
} }
void ResourceManager::pauseMusic() {
music.pause();
}
void ResourceManager::stopMusic() { void ResourceManager::stopMusic() {
music.stop(); music.stop();
} }
float ResourceManager::getMusicVolume() {
return music_volume;
}
void ResourceManager::setMusicVolume(float set_music_volume) {
music_volume = set_music_volume;
music.setVolume(music_volume);
}