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();
/**
* 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é

View File

@ -3,13 +3,22 @@
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <map>
#include <unordered_map>
#include <string>
#include <fstream>
#include <memory>
typedef std::unique_ptr<std::ifstream> LevelReader;
typedef std::unique_ptr<std::ofstream> LevelWriter;
class ResourceManager {
private:
std::map<std::string, sf::Texture> textures;
std::map<std::string, sf::Font> fonts;
std::string resources_dir;
std::unordered_map<std::string, sf::Texture> textures;
std::unordered_map<std::string, sf::Font> 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

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() {
Level::begin();
getResourceManager().playMusic("editor.ogg");
getWindow().setFramerateLimit(60);
}

View File

@ -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<char*>(&total_time), sizeof(total_time));
file->read(reinterpret_cast<char*>(&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<char*>(&pos_x), sizeof(pos_x));
file.read(reinterpret_cast<char*>(&pos_y), sizeof(pos_y));
file->read(reinterpret_cast<char*>(&pos_x), sizeof(pos_x));
file->read(reinterpret_cast<char*>(&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<char*>(&block_count), sizeof(block_count));
file->read(reinterpret_cast<char*>(&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();
}
}

View File

@ -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) {}

View File

@ -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<sf::Event>& 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> game = std::shared_ptr<Game>(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);
}

View File

@ -1,20 +1,18 @@
#include "resource_manager.hpp"
#include "whereami.h"
#include <memory>
#include <cstring>
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<char[]> buffer = std::unique_ptr<char[]>(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);
}