Re-fusion des méthodes #save(), suppression de getLevelName à réimplémenter dans

le menu pour son usage particulier & en même temps que les miniatures
This commit is contained in:
Mattéo Delabre 2016-04-19 20:34:25 +02:00
parent 837621d18b
commit 4cfd02e099
2 changed files with 128 additions and 161 deletions

View File

@ -24,7 +24,7 @@ private:
GravityDirection gravity_direction; GravityDirection gravity_direction;
sf::String name; sf::String name;
std::string current_path; std::string path;
int total_time; int total_time;
@ -64,27 +64,24 @@ public:
virtual void enable(); virtual void enable();
/** /**
* Obtient le nom du niveau dont le chemin complet * Charge le niveau de jeu donné depuis le fichier actuel
* et absolu est en paramètre
*/ */
static sf::String getLevelName(std::string path); void load();
/** /**
* Charge le niveau de jeu donné depuis le fichier * Sauvegarde la configuration actuelle dans le fichier actuel
* dont le chemin complet absolu est en paramètre
*/
void load(std::string path);
/**
* Écrase le niveau chargé avec les données en mémoire
*/ */
void save(); void save();
/** /**
* Sauvegarde la configuration actuelle dans le fichier donné * Récupère le chemin actuel du fichier du niveau
* dont le chemin complet absolu est donné en paramètre
*/ */
void save(std::string path); std::string getPath();
/**
* Modifie le chemin actuel du fichier du niveau
*/
void setPath(std::string set_path);
/** /**
* Traite l'événement donné * Traite l'événement donné

View File

@ -8,7 +8,6 @@
#include "finish_block.hpp" #include "finish_block.hpp"
#include "kill_block.hpp" #include "kill_block.hpp"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <iostream>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <cstring> #include <cstring>
#include <functional> #include <functional>
@ -47,109 +46,6 @@ namespace {
{KillBlock::TYPE_ID, KillBlock::load}, {KillBlock::TYPE_ID, KillBlock::load},
{SwitchBlock::TYPE_ID, SwitchBlock::load} {SwitchBlock::TYPE_ID, SwitchBlock::load}
}; };
/**
* Lecture du niveau dont le chemin absolu complet est en paramètre.
* Les métadonnées sont stockées dans les variables passées par référence.
* La callback object() est appelée séquentiellement avec les objets du niveau
*/
void loadLevel(
std::string path, sf::String& name, int& total_time,
std::vector<sf::Vector2f>& zone,
std::string& background, std::string& music,
std::function<Object::Ptr(Object::Ptr)> object_callback = {}
) {
// ouverture du fichier
std::ifstream file;
file.open(path, std::ios::binary | std::ios::in);
// on vérifie que le fichier ait correctement été ouvert en lecture
if (file.fail()) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(" + std::string(strerror(errno)) + ")"
);
}
// lecture de la signature du fichier ("BAR")
char signature[3];
file.read(signature, 3);
if (strncmp(signature, "BAR", 3) != 0) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(en-tête invalide)"
);
}
// lecture de la version du fichier
char file_version;
file.read(&file_version, 1);
if (file_version != VERSION_NUMBER) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(version non prise en charge)"
);
}
// lecture du nom du niveau
std::string std_name;
std::getline(file, std_name, '\0');
name = sf::String(std_name);
// lecture du temps total du niveau
file.read(reinterpret_cast<char*>(&total_time), 4);
total_time = ntohl(total_time);
// lecture de la zone de jeu
char control_points;
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), 4);
file.read(reinterpret_cast<char*>(&pos_y), 4);
pos_x *= Manager::GRID;
pos_y *= Manager::GRID;
zone.push_back(sf::Vector2f(pos_x, pos_y));
}
// lecture des chemins de la musique et du fond
std::getline(file, music, '\0');
std::getline(file, background, '\0');
// lecture des objets si une callback a été fournie
int object_count;
if (!object_callback) {
return;
}
file.read(reinterpret_cast<char*>(&object_count), 4);
object_count = ntohl(object_count);
for (int i = 0; i < object_count; i++) {
char object_type;
file.read(&object_type, 1);
// vérifie que le type est pris en charge
// pour éviter une erreur de segmentation
if (object_type_map.count(object_type) == 0) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(type d'objet " + std::to_string(object_type) + " inconnu)"
);
}
// lecture de l'objet
object_callback(object_type_map[object_type](file));
}
}
} }
Level::Level(Manager& manager) : State(manager) { Level::Level(Manager& manager) : State(manager) {
@ -157,7 +53,7 @@ Level::Level(Manager& manager) : State(manager) {
// métadonnées par défaut // métadonnées par défaut
setName(sf::String("Nouveau niveau")); setName(sf::String("Nouveau niveau"));
current_path = getResourceManager().getLevelPath("new_level.dat"); setPath(getResourceManager().getLevelPath("new_level.dat"));
setTotalTime(30); setTotalTime(30);
// zone de jeu par défaut // zone de jeu par défaut
@ -184,30 +80,102 @@ void Level::enable() {
camera_angle = 180.f; camera_angle = 180.f;
} }
sf::String Level::getLevelName(std::string path) { void Level::load() {
sf::String name; // ouverture du fichier
int total_time; std::ifstream file;
std::vector<sf::Vector2f> zone; file.open(path, std::ios::binary | std::ios::in);
std::string background;
std::string music;
loadLevel(path, name, total_time, zone, background, music); // on vérifie que le fichier ait correctement été ouvert en lecture
return name; if (file.fail()) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(" + std::string(strerror(errno)) + ")"
);
}
// lecture de la signature du fichier ("BAR")
char read_signature[3];
file.read(read_signature, 3);
if (strncmp(read_signature, "BAR", 3) != 0) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(en-tête invalide)"
);
}
// lecture de la version du fichier
char read_file_version;
file.read(&read_file_version, 1);
if (read_file_version != VERSION_NUMBER) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(version non prise en charge)"
);
}
// lecture du nom du niveau
std::string read_name;
std::getline(file, read_name, '\0');
setName(read_name);
// lecture du temps total du niveau
int read_total_time;
file.read(reinterpret_cast<char*>(&read_total_time), 4);
setTotalTime(ntohl(read_total_time));
// lecture de la zone de jeu
char read_control_points;
file.read(&read_control_points, 1);
zone.clear();
for (int i = 0; i < read_control_points; i++) {
float read_pos_x, read_pos_y;
file.read(reinterpret_cast<char*>(&read_pos_x), 4);
file.read(reinterpret_cast<char*>(&read_pos_y), 4);
read_pos_x *= Manager::GRID;
read_pos_y *= Manager::GRID;
zone.push_back(sf::Vector2f(read_pos_x, read_pos_y));
}
// lecture des chemins de la musique et du fond
std::string read_music;
std::string read_background;
std::getline(file, read_music, '\0');
std::getline(file, read_background, '\0');
setMusic(read_music);
setBackground(read_background);
// lecture des objets si une callback a été fournie
int read_object_count;
file.read(reinterpret_cast<char*>(&read_object_count), 4);
read_object_count = ntohl(read_object_count);
for (int i = 0; i < read_object_count; i++) {
char read_object_type;
file.read(&read_object_type, 1);
// vérifie que le type est pris en charge
// pour éviter une erreur de segmentation
if (object_type_map.count(read_object_type) == 0) {
throw std::runtime_error(
"Impossible de charger le niveau \"" + name + "\" " +
"(type d'objet " + std::to_string(read_object_type) + " inconnu)"
);
}
// lecture de l'objet
addObject(object_type_map[read_object_type](file));
}
} }
void Level::load(std::string path) { void Level::save() {
loadLevel(
path, name, total_time,
zone, background, music,
std::bind(&Level::addObject, this, std::placeholders::_1)
);
setTotalTime(total_time);
setMusic(music);
current_path = path;
}
void Level::save(std::string path) {
std::ofstream file; std::ofstream file;
file.open(path, std::ios::binary | std::ios::out); file.open(path, std::ios::binary | std::ios::out);
@ -220,31 +188,31 @@ void Level::save(std::string path) {
} }
// écriture de la signture du fichier ("BAR") // écriture de la signture du fichier ("BAR")
char signature[3] = {'B', 'A', 'R'}; char write_signature[3] = {'B', 'A', 'R'};
file.write(signature, 3); file.write(write_signature, 3);
// écriture de la version du fichier // écriture de la version du fichier
char file_version = VERSION_NUMBER; char write_file_version = VERSION_NUMBER;
file.write(&file_version, 1); file.write(&write_file_version, 1);
// écriture du nom du niveau // écriture du nom du niveau
char *write_name = (char*) name.toAnsiString().data(); char *write_name = (char*) name.toAnsiString().data();
file.write(write_name, name.getSize() + 1); file.write(write_name, name.getSize() + 1);
// écriture du temps total du niveau // écriture du temps total du niveau
int conv_total_time = htonl(total_time); int write_total_time = htonl(total_time);
file.write(reinterpret_cast<char*>(&conv_total_time), 4); file.write(reinterpret_cast<char*>(&write_total_time), 4);
// écriture de la zone de jeu // écriture de la zone de jeu
char control_points = (char) zone.size(); char write_control_points = (char) zone.size();
file.write(&control_points, 1); file.write(&write_control_points, 1);
for (int i = 0; i < control_points; i++) { for (int i = 0; i < write_control_points; i++) {
float pos_x = zone[i].x / Manager::GRID; float write_pos_x = zone[i].x / Manager::GRID;
float pos_y = zone[i].y / Manager::GRID; float write_pos_y = zone[i].y / Manager::GRID;
file.write(reinterpret_cast<char*>(&pos_x), 4); file.write(reinterpret_cast<char*>(&write_pos_x), 4);
file.write(reinterpret_cast<char*>(&pos_y), 4); file.write(reinterpret_cast<char*>(&write_pos_y), 4);
} }
// écriture des noms de la musique et du fond // écriture des noms de la musique et du fond
@ -255,22 +223,24 @@ void Level::save(std::string path) {
file.write(write_background, background.size() + 1); file.write(write_background, background.size() + 1);
// écriture des objets // écriture des objets
int object_count = htonl(objects.size()); int write_object_count = htonl(objects.size());
file.write(reinterpret_cast<char*>(&object_count), 4); file.write(reinterpret_cast<char*>(&write_object_count), 4);
for (unsigned int i = 0; i < objects.size(); i++) { for (unsigned int i = 0; i < objects.size(); i++) {
char object_type = objects[i]->getTypeId(); char write_object_type = objects[i]->getTypeId();
file.write(&object_type, 1); file.write(&write_object_type, 1);
// écriture de l'objet // écriture de l'objet
objects[i]->save(file); objects[i]->save(file);
} }
std::cout << "Sauvegardé : " << path << std::endl;
} }
void Level::save() { std::string Level::getPath() {
save(current_path); return path;
}
void Level::setPath(std::string set_path ){
path = set_path;
} }
void Level::processEvent(const sf::Event& event) { void Level::processEvent(const sf::Event& event) {