Sauvegarde des objets dans un fichier
This commit is contained in:
parent
b175b31643
commit
ed0f2f5ace
|
@ -64,6 +64,11 @@ public:
|
|||
* Chargement du bloc depuis le fichier donné
|
||||
*/
|
||||
static ObjectPtr load(std::ifstream& file);
|
||||
|
||||
/**
|
||||
* Sauvegarde le bloc dans le fichier donné
|
||||
*/
|
||||
virtual void save(std::ofstream& file) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,11 @@ public:
|
|||
*/
|
||||
static ObjectPtr load(std::ifstream& file);
|
||||
|
||||
/**
|
||||
* Sauvegarde le bloc de gravité dans le fichier donné
|
||||
*/
|
||||
virtual void save(std::ofstream& file) const;
|
||||
|
||||
/**
|
||||
* Récupère la direction de gravité du bloc changeur de gravité
|
||||
*/
|
||||
|
|
|
@ -24,8 +24,10 @@ private:
|
|||
|
||||
sf::String name;
|
||||
int total_time;
|
||||
sf::Sprite background;
|
||||
std::string music_name;
|
||||
|
||||
sf::Sprite background_sprite;
|
||||
std::string background;
|
||||
std::string music;
|
||||
|
||||
std::vector<ObjectPtr> objects;
|
||||
std::vector<std::pair<float, float>> zone;
|
||||
|
@ -56,12 +58,12 @@ public:
|
|||
/**
|
||||
* Charge un niveau de jeu avec le nom donné
|
||||
*/
|
||||
virtual void load(std::string name);
|
||||
virtual void load(std::string filename);
|
||||
|
||||
/**
|
||||
* Sauvegarde la configuration actuelle dans le niveau donné
|
||||
*/
|
||||
virtual void save(std::string name);
|
||||
virtual void save(std::string filename);
|
||||
|
||||
/**
|
||||
* Appelé par le manager lorsque l'état est utilisé
|
||||
|
@ -93,15 +95,25 @@ public:
|
|||
*/
|
||||
void setTotalTime(int set_total_time);
|
||||
|
||||
/**
|
||||
* Récupère la musique du niveau
|
||||
*/
|
||||
std::string getMusic() const;
|
||||
|
||||
/**
|
||||
* Modifie la musique du niveau
|
||||
*/
|
||||
void setMusic(std::string set_music);
|
||||
|
||||
/**
|
||||
* Récupère le fond du niveau
|
||||
*/
|
||||
sf::Sprite getBackground() const;
|
||||
std::string getBackground() const;
|
||||
|
||||
/**
|
||||
* Modifie le fond du niveau
|
||||
*/
|
||||
void setBackground(sf::Sprite set_background);
|
||||
void setBackground(std::string set_background);
|
||||
|
||||
/**
|
||||
* Calcule le vecteur gravité en fonction de la direction de la gravité
|
||||
|
|
|
@ -89,6 +89,11 @@ public:
|
|||
*/
|
||||
static void load(std::ifstream& file, ObjectPtr object);
|
||||
|
||||
/**
|
||||
* Sauvegarde cet objet dans le fichier donné
|
||||
*/
|
||||
virtual void save(std::ofstream& file) const = 0;
|
||||
|
||||
/**
|
||||
* Met à jour la vitesse de l'objet selon les
|
||||
* forces qui lui sont appliquées
|
||||
|
|
|
@ -64,6 +64,11 @@ public:
|
|||
*/
|
||||
static ObjectPtr load(std::ifstream& file);
|
||||
|
||||
/**
|
||||
* Sauvegarde le joueur dans le fichier donné
|
||||
*/
|
||||
virtual void save(std::ofstream& file) const;
|
||||
|
||||
/**
|
||||
* Met à jour la position de l'objet selon sa
|
||||
* vitesse actuelle
|
||||
|
|
|
@ -32,6 +32,11 @@ ObjectPtr Block::load(std::ifstream& file) {
|
|||
return object;
|
||||
}
|
||||
|
||||
void Block::save(std::ofstream& file) const {
|
||||
// écriture des propriétés communes
|
||||
Object::save(file);
|
||||
}
|
||||
|
||||
void Block::beforeDraw(Level& level) {
|
||||
// texturage et coloration du bloc selon ses propriétés
|
||||
sprite.setTexture(
|
||||
|
|
|
@ -385,6 +385,7 @@ void Editor::test() {
|
|||
game->setName(getName());
|
||||
game->setTotalTime(getTotalTime());
|
||||
game->setBackground(getBackground());
|
||||
game->setMusic(getMusic());
|
||||
|
||||
// copie des objets du niveau vers le jeu
|
||||
std::vector<ObjectPtr>& objects = getObjects();
|
||||
|
|
|
@ -52,21 +52,29 @@ unsigned int GravityBlock::getTypeId() const {
|
|||
}
|
||||
|
||||
ObjectPtr GravityBlock::load(std::ifstream& file) {
|
||||
ObjectPtr object = ObjectPtr(new GravityBlock);
|
||||
std::shared_ptr<GravityBlock> block = std::dynamic_pointer_cast<GravityBlock>(object);
|
||||
|
||||
// lecture de la direction de la gravité
|
||||
char gravity_direction;
|
||||
file.read(&gravity_direction, 1);
|
||||
|
||||
// lecture des propriétés d'un bloc
|
||||
ObjectPtr object = Block::load(file);
|
||||
std::shared_ptr<GravityBlock> block = std::dynamic_pointer_cast<GravityBlock>(object);
|
||||
|
||||
// attribution de la direction
|
||||
block->setGravityDirection((GravityDirection) gravity_direction);
|
||||
|
||||
// lecture des propriétés communes des objets
|
||||
Object::load(file, object);
|
||||
file.seekg(1, file.cur);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void GravityBlock::save(std::ofstream& file) const {
|
||||
// écriture de la direction de la gravité
|
||||
char write_gravity_direction = (char) gravity_direction;
|
||||
file.write(&write_gravity_direction, 1);
|
||||
|
||||
// écriture des propriétés d'un bloc
|
||||
Block::save(file);
|
||||
}
|
||||
|
||||
GravityDirection GravityBlock::getGravityDirection() const {
|
||||
return gravity_direction;
|
||||
}
|
||||
|
|
123
src/level.cpp
123
src/level.cpp
|
@ -19,6 +19,11 @@ const float GRAVITY = 235;
|
|||
*/
|
||||
const float MOVE = 200;
|
||||
|
||||
/**
|
||||
* Numéro actuel de version du format de fichier
|
||||
*/
|
||||
const unsigned int VERSION_NUMBER = 0;
|
||||
|
||||
/**
|
||||
* Dictionnaire associant les types d'objets
|
||||
* à des instances qui seront utilisées pour la
|
||||
|
@ -33,8 +38,8 @@ std::map<unsigned int, std::function<ObjectPtr(std::ifstream&)>> object_type_map
|
|||
Level::Level(Manager& manager) : State(manager) {}
|
||||
Level::~Level() {}
|
||||
|
||||
void Level::load(std::string name) {
|
||||
std::ifstream file = getResourceManager().getLevelReader(name);
|
||||
void Level::load(std::string filename) {
|
||||
std::ifstream file = getResourceManager().getLevelReader(filename);
|
||||
|
||||
// vidage du niveau précédent et positionnement
|
||||
// de la caméra au centre du niveau
|
||||
|
@ -43,9 +48,9 @@ void Level::load(std::string name) {
|
|||
|
||||
// lecture de la signture du fichier ("BAR")
|
||||
char signature[3];
|
||||
file.read(signature, sizeof(signature));
|
||||
file.read(signature, 3);
|
||||
|
||||
if (strncmp(signature, "BAR", sizeof(signature)) != 0) {
|
||||
if (strncmp(signature, "BAR", 3) != 0) {
|
||||
throw std::runtime_error(
|
||||
"Impossible de lire le fichier : en-tête invalide"
|
||||
);
|
||||
|
@ -55,7 +60,7 @@ void Level::load(std::string name) {
|
|||
char file_version;
|
||||
file.read(&file_version, 1);
|
||||
|
||||
if (file_version != 0) {
|
||||
if (file_version != VERSION_NUMBER) {
|
||||
throw std::runtime_error(
|
||||
"Impossible de lire le fichier : version non prise en charge"
|
||||
);
|
||||
|
@ -67,7 +72,7 @@ void Level::load(std::string name) {
|
|||
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), 4);
|
||||
total_time = ntohl(total_time);
|
||||
|
||||
// lecture de la zone de jeu
|
||||
|
@ -78,8 +83,8 @@ void Level::load(std::string name) {
|
|||
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), 4);
|
||||
file.read(reinterpret_cast<char*>(&pos_y), 4);
|
||||
|
||||
pos_x *= Constants::GRID;
|
||||
pos_y *= Constants::GRID;
|
||||
|
@ -88,50 +93,95 @@ void Level::load(std::string name) {
|
|||
}
|
||||
|
||||
// lecture des chemins de la musique et du fond
|
||||
std::string background_name;
|
||||
std::getline(file, music, '\0');
|
||||
std::getline(file, background, '\0');
|
||||
|
||||
std::getline(file, music_name, '\0');
|
||||
std::getline(file, background_name, '\0');
|
||||
background.setTexture(getResourceManager().getTexture(background_name));
|
||||
// lecture des objets
|
||||
int object_count;
|
||||
|
||||
// lecture du nombre de blocs
|
||||
int block_count;
|
||||
file.read(reinterpret_cast<char*>(&object_count), 4);
|
||||
object_count = ntohl(object_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);
|
||||
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(block_type) == 0) {
|
||||
if (object_type_map.count(object_type) == 0) {
|
||||
throw std::runtime_error(
|
||||
"Impossible de lire le fichier : type d'objet inconnu"
|
||||
);
|
||||
}
|
||||
|
||||
objects.push_back(object_type_map[block_type](file));
|
||||
// lecture de l'objet
|
||||
objects.push_back(object_type_map[object_type](file));
|
||||
}
|
||||
}
|
||||
|
||||
void Level::save(std::string name) {
|
||||
std::ofstream file = getResourceManager().getLevelWriter(name);
|
||||
void Level::save(std::string filename) {
|
||||
std::ofstream file = getResourceManager().getLevelWriter(filename);
|
||||
|
||||
// TODO: faire une fonction d'enregistrement
|
||||
// écriture de la signture du fichier ("BAR")
|
||||
char signature[3] = {'B', 'A', 'R'};
|
||||
file.write(signature, 3);
|
||||
|
||||
// écriture de la version du fichier
|
||||
char file_version = VERSION_NUMBER;
|
||||
file.write(&file_version, 1);
|
||||
|
||||
// écriture du nom du niveau
|
||||
char *write_name = (char*) name.toAnsiString().data();
|
||||
file.write(write_name, name.getSize() + 1);
|
||||
|
||||
// écriture du temps total du niveau
|
||||
int conv_total_time = htonl(total_time);
|
||||
file.write(reinterpret_cast<char*>(&conv_total_time), 4);
|
||||
|
||||
// écriture de la zone de jeu
|
||||
char control_points = (char) zone.size();
|
||||
file.write(&control_points, 1);
|
||||
|
||||
for (int i = 0; i < control_points; i++) {
|
||||
float pos_x = std::get<0>(zone[i]) / Constants::GRID;
|
||||
float pos_y = std::get<1>(zone[i]) / Constants::GRID;
|
||||
|
||||
file.write(reinterpret_cast<char*>(&pos_x), 4);
|
||||
file.write(reinterpret_cast<char*>(&pos_y), 4);
|
||||
}
|
||||
|
||||
// écriture des noms de la musique et du fond
|
||||
char *write_music = (char*) music.data();
|
||||
file.write(write_music, music.size() + 1);
|
||||
|
||||
char *write_background = (char*) background.data();
|
||||
file.write(write_background, background.size() + 1);
|
||||
|
||||
// écriture des objets
|
||||
int object_count = htonl(objects.size());
|
||||
file.write(reinterpret_cast<char*>(&object_count), 4);
|
||||
|
||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
||||
char object_type = objects[i]->getTypeId();
|
||||
file.write(&object_type, 1);
|
||||
|
||||
// écriture de l'objet
|
||||
objects[i]->save(file);
|
||||
}
|
||||
}
|
||||
|
||||
void Level::begin() {
|
||||
// TODO: ceci ne devrait pas être là
|
||||
// (imaginons que l'on quitte et revienne à un niveau)
|
||||
// (il faudra réfléchir à abandonner le concept de ::begin())
|
||||
|
||||
camera = getWindow().getDefaultView();
|
||||
camera.setCenter(0, 0);
|
||||
camera_angle = 180.f;
|
||||
gravity_direction = GravityDirection::SOUTH;
|
||||
|
||||
if (music_name != "") {
|
||||
getResourceManager().playMusic(music_name);
|
||||
if (music != "") {
|
||||
getResourceManager().playMusic(music);
|
||||
} else {
|
||||
getResourceManager().stopMusic();
|
||||
}
|
||||
|
@ -164,7 +214,12 @@ void Level::draw() {
|
|||
|
||||
// efface la scène précédente et dessine la couche de fond
|
||||
window.clear(sf::Color(66, 165, 245));
|
||||
window.draw(background);
|
||||
|
||||
if (background != "") {
|
||||
background_sprite.setTexture(getResourceManager().getTexture(background));
|
||||
}
|
||||
|
||||
window.draw(background_sprite);
|
||||
|
||||
// chargement de la file d'affichage des objets
|
||||
std::priority_queue<ObjectPtr, std::vector<ObjectPtr>, ObjectCompare> display_queue;
|
||||
|
@ -203,11 +258,19 @@ void Level::setTotalTime(int set_total_time) {
|
|||
total_time = set_total_time;
|
||||
}
|
||||
|
||||
sf::Sprite Level::getBackground() const {
|
||||
std::string Level::getMusic() const {
|
||||
return music;
|
||||
}
|
||||
|
||||
void Level::setMusic(std::string set_music) {
|
||||
music = set_music;
|
||||
}
|
||||
|
||||
std::string Level::getBackground() const {
|
||||
return background;
|
||||
}
|
||||
|
||||
void Level::setBackground(sf::Sprite set_background) {
|
||||
void Level::setBackground(std::string set_background) {
|
||||
background = set_background;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,17 @@
|
|||
#include <cmath>
|
||||
|
||||
const unsigned int Object::PROP_MASS = 1;
|
||||
const float DEFAULT_MASS = 1.f;
|
||||
const unsigned int Object::PROP_CHARGE = 2;
|
||||
const float DEFAULT_CHARGE = 0.f;
|
||||
const unsigned int Object::PROP_RESTITUTION = 3;
|
||||
const float DEFAULT_RESTITUTION = 0.4f;
|
||||
const unsigned int Object::PROP_STATIC_FRICTION = 4;
|
||||
const float DEFAULT_STATIC_FRICTION = 0.4f;
|
||||
const unsigned int Object::PROP_DYNAMIC_FRICTION = 5;
|
||||
const float DEFAULT_DYNAMIC_FRICTION = 0.2f;
|
||||
const unsigned int Object::PROP_LAYER = 6;
|
||||
const int DEFAULT_LAYER = 0;
|
||||
|
||||
Object::Object() :
|
||||
acceleration(0, 0), velocity(0, 0), position(0, 0),
|
||||
|
@ -17,11 +23,12 @@ Object::Object() :
|
|||
|
||||
// valeurs par défaut pour les propriétés
|
||||
// de tous les objets du jeu
|
||||
mass(1.f), charge(0.f),
|
||||
restitution(0.4f),
|
||||
static_friction(0.4f),
|
||||
dynamic_friction(0.2f),
|
||||
layer(0) {}
|
||||
mass(DEFAULT_MASS),
|
||||
charge(DEFAULT_CHARGE),
|
||||
restitution(DEFAULT_RESTITUTION),
|
||||
static_friction(DEFAULT_STATIC_FRICTION),
|
||||
dynamic_friction(DEFAULT_DYNAMIC_FRICTION),
|
||||
layer(DEFAULT_LAYER) {}
|
||||
|
||||
Object::~Object() {}
|
||||
|
||||
|
@ -29,8 +36,8 @@ void Object::load(std::ifstream& file, ObjectPtr object) {
|
|||
// lecture de la position de l'objet
|
||||
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), 4);
|
||||
file.read(reinterpret_cast<char*>(&pos_y), 4);
|
||||
|
||||
object->setPosition(sf::Vector2f(
|
||||
pos_x * Constants::GRID, pos_y * Constants::GRID
|
||||
|
@ -43,31 +50,31 @@ void Object::load(std::ifstream& file, ObjectPtr object) {
|
|||
switch (prop_type) {
|
||||
case Object::PROP_MASS:
|
||||
float mass;
|
||||
file.read(reinterpret_cast<char*>(&mass), sizeof(mass));
|
||||
file.read(reinterpret_cast<char*>(&mass), 4);
|
||||
object->setMass(mass);
|
||||
break;
|
||||
|
||||
case Object::PROP_CHARGE:
|
||||
float charge;
|
||||
file.read(reinterpret_cast<char*>(&charge), sizeof(charge));
|
||||
file.read(reinterpret_cast<char*>(&charge), 4);
|
||||
object->setCharge(charge);
|
||||
break;
|
||||
|
||||
case Object::PROP_RESTITUTION:
|
||||
float restitution;
|
||||
file.read(reinterpret_cast<char*>(&restitution), sizeof(restitution));
|
||||
file.read(reinterpret_cast<char*>(&restitution), 4);
|
||||
object->setRestitution(restitution);
|
||||
break;
|
||||
|
||||
case Object::PROP_STATIC_FRICTION:
|
||||
float static_friction;
|
||||
file.read(reinterpret_cast<char*>(&static_friction), sizeof(static_friction));
|
||||
file.read(reinterpret_cast<char*>(&static_friction), 4);
|
||||
object->setStaticFriction(static_friction);
|
||||
break;
|
||||
|
||||
case Object::PROP_DYNAMIC_FRICTION:
|
||||
float dynamic_friction;
|
||||
file.read(reinterpret_cast<char*>(&dynamic_friction), sizeof(dynamic_friction));
|
||||
file.read(reinterpret_cast<char*>(&dynamic_friction), 4);
|
||||
object->setDynamicFriction(dynamic_friction);
|
||||
break;
|
||||
|
||||
|
@ -86,6 +93,60 @@ void Object::load(std::ifstream& file, ObjectPtr object) {
|
|||
}
|
||||
}
|
||||
|
||||
void Object::save(std::ofstream& file) const {
|
||||
// écriture de la position de l'objet
|
||||
float pos_x = getPosition().x / Constants::GRID;
|
||||
float pos_y = getPosition().y / Constants::GRID;
|
||||
|
||||
file.write(reinterpret_cast<const char*>(&pos_x), 4);
|
||||
file.write(reinterpret_cast<const char*>(&pos_y), 4);
|
||||
|
||||
// écriture des propriétés facultatives si nécessaire
|
||||
char prop_type;
|
||||
|
||||
if (mass != DEFAULT_MASS) {
|
||||
prop_type = Object::PROP_MASS;
|
||||
file.write(&prop_type, 1);
|
||||
file.write(reinterpret_cast<const char*>(&mass), 4);
|
||||
}
|
||||
|
||||
if (charge != DEFAULT_CHARGE) {
|
||||
prop_type = Object::PROP_CHARGE;
|
||||
file.write(&prop_type, 1);
|
||||
file.write(reinterpret_cast<const char*>(&charge), 4);
|
||||
}
|
||||
|
||||
if (restitution != DEFAULT_RESTITUTION) {
|
||||
prop_type = Object::PROP_RESTITUTION;
|
||||
file.write(&prop_type, 1);
|
||||
file.write(reinterpret_cast<const char*>(&restitution), 4);
|
||||
}
|
||||
|
||||
if (static_friction != DEFAULT_STATIC_FRICTION) {
|
||||
prop_type = Object::PROP_STATIC_FRICTION;
|
||||
file.write(&prop_type, 1);
|
||||
file.write(reinterpret_cast<const char*>(&static_friction), 4);
|
||||
}
|
||||
|
||||
if (dynamic_friction != DEFAULT_DYNAMIC_FRICTION) {
|
||||
prop_type = Object::PROP_DYNAMIC_FRICTION;
|
||||
file.write(&prop_type, 1);
|
||||
file.write(reinterpret_cast<const char*>(&dynamic_friction), 4);
|
||||
}
|
||||
|
||||
if (layer != DEFAULT_LAYER) {
|
||||
prop_type = Object::PROP_LAYER;
|
||||
file.write(&prop_type, 1);
|
||||
|
||||
char write_layer = layer + 127;
|
||||
file.write(&write_layer, 1);
|
||||
}
|
||||
|
||||
// on termine par un octet nul pour signaler la fin
|
||||
char null_byte = 0;
|
||||
file.write(&null_byte, 1);
|
||||
}
|
||||
|
||||
sf::Vector2f Object::getForces(const Level& level) const {
|
||||
sf::Vector2f forces(0, 0);
|
||||
const std::vector<ObjectPtr>& objects = level.getObjects();
|
||||
|
|
|
@ -34,6 +34,15 @@ ObjectPtr Player::load(std::ifstream& file) {
|
|||
return object;
|
||||
}
|
||||
|
||||
void Player::save(std::ofstream& file) const {
|
||||
// écriture du numéro de joueur
|
||||
char write_player_number = player_number;
|
||||
file.write(&write_player_number, 1);
|
||||
|
||||
// écriture des propriétés communes
|
||||
Object::save(file);
|
||||
}
|
||||
|
||||
sf::Vector2f Player::getForces(const Level& level) const {
|
||||
sf::Vector2f forces = Object::getForces(level);
|
||||
|
||||
|
|
Loading…
Reference in New Issue