Abstraction de la classe Game en Level pour accueillir Editor
This commit is contained in:
		
							parent
							
								
									5df9190c0a
								
							
						
					
					
						commit
						26a363ad10
					
				|  | @ -1,6 +1,8 @@ | |||
| #ifndef __PTF_CONSTANTS_HPP__ | ||||
| #define __PTF_CONSTANTS_HPP__ | ||||
| 
 | ||||
| #include <SFML/System.hpp> | ||||
| 
 | ||||
| namespace Constants { | ||||
|     /**
 | ||||
|      * Constante d'attraction. Utilisée dans la formule | ||||
|  |  | |||
|  | @ -1,53 +1,26 @@ | |||
| #ifndef __PTF_GAME_HPP__ | ||||
| #define __PTF_GAME_HPP__ | ||||
| 
 | ||||
| #include <SFML/Audio.hpp> | ||||
| #include <fstream> | ||||
| #include <vector> | ||||
| #include "view.hpp" | ||||
| #include "object.hpp" | ||||
| #include "manager.hpp" | ||||
| #include "resource_manager.hpp" | ||||
| #include "level.hpp" | ||||
| 
 | ||||
| /**
 | ||||
|  * La classe Game gère l'affichage et les objets | ||||
|  * d'une partie de jeu | ||||
|  */ | ||||
| class Game : public View { | ||||
| class Game : public Level { | ||||
| private: | ||||
|     std::string level_name; | ||||
|     sf::Sprite background; | ||||
| 
 | ||||
|     sf::Time next_frame_time; | ||||
| 
 | ||||
|     std::vector<ObjectPtr> objects; | ||||
|     std::vector<std::pair<float, float>> level_zone; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Met à jour les objets du jeu pour | ||||
|      * qu'ils s'adaptent au nouvel état | ||||
|      */ | ||||
|     void update(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Dessine la scène du jeu couche par couche | ||||
|      */ | ||||
|     void draw(); | ||||
| 
 | ||||
| public: | ||||
|     Game(Manager& manager); | ||||
|     virtual ~Game(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Charge un niveau de jeu depuis le fichier donné | ||||
|      */ | ||||
|     void load(std::ifstream& file); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sauvegarde la configuration actuelle comme un niveau | ||||
|      */ | ||||
|     void save(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Demande le passage à la frame suivante sur | ||||
|      * cette vue | ||||
|  |  | |||
|  | @ -0,0 +1,60 @@ | |||
| #ifndef __PTF_OBJECT_VIEW_HPP__ | ||||
| #define __PTF_OBJECT_VIEW_HPP__ | ||||
| 
 | ||||
| #include <fstream> | ||||
| #include <vector> | ||||
| #include "view.hpp" | ||||
| #include "object.hpp" | ||||
| #include "manager.hpp" | ||||
| #include "resource_manager.hpp" | ||||
| 
 | ||||
| /**
 | ||||
|  * La classe Level est une abstraction des | ||||
|  * classes affichant une collection d'objets, comme | ||||
|  * les classe de l'éditeur et du jeu | ||||
|  */ | ||||
| class Level : public View { | ||||
| private: | ||||
|     std::string name; | ||||
|     sf::Sprite background; | ||||
| 
 | ||||
|     std::vector<ObjectPtr> objects; | ||||
|     std::vector<std::pair<float, float>> zone; | ||||
| 
 | ||||
| protected: | ||||
|     /**
 | ||||
|      * Dessine tous les objets et le fond à l'écran | ||||
|      */ | ||||
|     void draw(); | ||||
| 
 | ||||
| public: | ||||
|     Level(Manager& manager); | ||||
|     virtual ~Level(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Charge un niveau de jeu depuis le fichier donné | ||||
|      */ | ||||
|     void load(std::ifstream& file); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Sauvegarde la configuration actuelle comme un niveau | ||||
|      */ | ||||
|     void save(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère le nom du niveau | ||||
|      */ | ||||
|     std::string getName(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère la liste des objets | ||||
|      */ | ||||
|     std::vector<ObjectPtr> getObjects(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère la zone du niveau | ||||
|      */ | ||||
|     std::vector<std::pair<float, float>> getZone(); | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										151
									
								
								src/game.cpp
								
								
								
								
							
							
						
						
									
										151
									
								
								src/game.cpp
								
								
								
								
							|  | @ -1,114 +1,9 @@ | |||
| #include "game.hpp" | ||||
| #include "constants.hpp" | ||||
| #include "object.hpp" | ||||
| #include "block.hpp" | ||||
| #include "player.hpp" | ||||
| #include <arpa/inet.h> | ||||
| #include <cstring> | ||||
| #include <queue> | ||||
| #include <utility> | ||||
| #include <iostream> | ||||
| 
 | ||||
| /**
 | ||||
|  * Dictionnaire associant les types d'objets | ||||
|  * à des instances qui seront utilisées pour la | ||||
|  * construction d'autres objets de ces types | ||||
|  */ | ||||
| std::map<unsigned int, std::function<std::shared_ptr<Object>(std::ifstream&)>> object_type_map = { | ||||
|     {Player::TYPE_ID, Player::load}, | ||||
|     {Block::TYPE_ID, Block::load} | ||||
| }; | ||||
| 
 | ||||
| Game::Game(Manager& manager) : View(manager), | ||||
| Game::Game(Manager& manager) : Level(manager), | ||||
|     next_frame_time(manager.getCurrentTime()) {} | ||||
| 
 | ||||
| Game::~Game() { | ||||
|     objects.clear(); | ||||
| } | ||||
| 
 | ||||
| void Game::load(std::ifstream& file) { | ||||
|     // vide le niveau précédent s'il y a lieu
 | ||||
|     if (objects.size() != 0) { | ||||
|         objects.clear(); | ||||
|     } | ||||
| 
 | ||||
|     // lecture de la signture du fichier ("BAR")
 | ||||
|     char signature[3]; | ||||
|     file.read(signature, sizeof(signature)); | ||||
| 
 | ||||
|     if (strncmp(signature, "BAR", sizeof(signature)) != 0) { | ||||
|         throw std::runtime_error( | ||||
|             "Impossible de lire le fichier : en-tête invalide" | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     // lecture de la version du fichier
 | ||||
|     char file_version; | ||||
|     file.read(&file_version, 1); | ||||
| 
 | ||||
|     if (file_version != 0) { | ||||
|         throw std::runtime_error( | ||||
|             "Impossible de lire le fichier : version non prise en charge" | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     // lecture du nom du niveau
 | ||||
|     std::getline(file, level_name, '\0'); | ||||
| 
 | ||||
|     // lecture de la zone de jeu
 | ||||
|     char control_points; | ||||
|     file.read(&control_points, 1); | ||||
|     level_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)); | ||||
| 
 | ||||
|         pos_x *= Constants::GRID; | ||||
|         pos_y *= Constants::GRID; | ||||
| 
 | ||||
|         level_zone.push_back(std::make_pair(pos_x, pos_y)); | ||||
|     } | ||||
| 
 | ||||
|     // lecture des chemins de la musique et du fond
 | ||||
|     std::string music_name, background_name; | ||||
|     ResourceManager& resource_manager = manager.getResourceManager(); | ||||
| 
 | ||||
|     std::getline(file, music_name, '\0'); | ||||
|     resource_manager.setMusic(music_name); | ||||
|     resource_manager.playMusic(); | ||||
| 
 | ||||
|     std::getline(file, background_name, '\0'); | ||||
|     background.setTexture(resource_manager.getTexture(background_name)); | ||||
| 
 | ||||
|     // lecture du nombre de blocs
 | ||||
|     int 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); | ||||
| 
 | ||||
|         // vérifie que le type est pris en charge
 | ||||
|         // pour éviter une erreur de segmentation
 | ||||
|         if (object_type_map.count(block_type) == 0) { | ||||
|             throw std::runtime_error( | ||||
|                 "Impossible de lire le fichier : type d'objet inconnu" | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         objects.push_back(object_type_map[block_type](file)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Game::save() { | ||||
|     // TODO: faire une fonction d'enregistrement
 | ||||
|     // TODO: migrer sur une classe commune Game <-> Editor
 | ||||
| } | ||||
| Game::~Game() {} | ||||
| 
 | ||||
| void Game::frame() { | ||||
|     sf::Time current_time = manager.getCurrentTime(); | ||||
|  | @ -136,11 +31,11 @@ void Game::update() { | |||
|     std::vector<CollisionData> colliding; | ||||
| 
 | ||||
|     // détection des objets en collision
 | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         ObjectPtr objA = objects[i]; | ||||
|     for (unsigned int i = 0; i < getObjects().size(); i++) { | ||||
|         ObjectPtr objA = getObjects()[i]; | ||||
| 
 | ||||
|         for (unsigned int j = i + 1; j < objects.size(); j++) { | ||||
|             ObjectPtr objB = objects[j]; | ||||
|         for (unsigned int j = i + 1; j < getObjects().size(); j++) { | ||||
|             ObjectPtr objB = getObjects()[j]; | ||||
|             CollisionData data(*objA, *objB); | ||||
| 
 | ||||
|             if (objA->detectCollision(*objB, data)) { | ||||
|  | @ -150,8 +45,8 @@ void Game::update() { | |||
|     } | ||||
| 
 | ||||
|     // intégration des forces dans la vitesse (première moitié)
 | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         objects[i]->updateVelocity(manager, objects, Constants::PHYSICS_TIME.asSeconds() / 2); | ||||
|     for (unsigned int i = 0; i < getObjects().size(); i++) { | ||||
|         getObjects()[i]->updateVelocity(manager, getObjects(), Constants::PHYSICS_TIME.asSeconds() / 2); | ||||
|     } | ||||
| 
 | ||||
|     // résolution des collisions détectées
 | ||||
|  | @ -161,8 +56,8 @@ void Game::update() { | |||
|     } | ||||
| 
 | ||||
|     // intégration de la vitesse dans la position
 | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         objects[i]->updatePosition(Constants::PHYSICS_TIME.asSeconds()); | ||||
|     for (unsigned int i = 0; i < getObjects().size(); i++) { | ||||
|         getObjects()[i]->updatePosition(Constants::PHYSICS_TIME.asSeconds()); | ||||
|     } | ||||
| 
 | ||||
|     // application de la correction positionnelle
 | ||||
|  | @ -174,29 +69,7 @@ void Game::update() { | |||
|     } | ||||
| 
 | ||||
|     // intégration des forces dans la vitesse (seconde moitié)
 | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         objects[i]->updateVelocity(manager, objects, Constants::PHYSICS_TIME.asSeconds() / 2); | ||||
|     for (unsigned int i = 0; i < getObjects().size(); i++) { | ||||
|         getObjects()[i]->updateVelocity(manager, getObjects(), Constants::PHYSICS_TIME.asSeconds() / 2); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Game::draw() { | ||||
|     // efface la scène précédente et dessine la couche de fond
 | ||||
|     sf::RenderWindow& window = manager.getWindow(); | ||||
|     window.clear(sf::Color(66, 165, 245)); | ||||
|     window.draw(background); | ||||
| 
 | ||||
|     // chargement de la file d'affichage des objets
 | ||||
|     std::priority_queue<ObjectPtr, std::vector<ObjectPtr>, ObjectCompare> display_queue; | ||||
| 
 | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         display_queue.push(objects[i]); | ||||
|     } | ||||
| 
 | ||||
|     // dessin des objets de la file d'affichage couche par couche
 | ||||
|     while (!display_queue.empty()) { | ||||
|         display_queue.top()->draw(manager); | ||||
|         display_queue.pop(); | ||||
|     } | ||||
| 
 | ||||
|     window.display(); | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,140 @@ | |||
| #include "constants.hpp" | ||||
| #include "block.hpp" | ||||
| #include "player.hpp" | ||||
| #include <arpa/inet.h> | ||||
| #include <cstring> | ||||
| #include <queue> | ||||
| #include <utility> | ||||
| #include "level.hpp" | ||||
| 
 | ||||
| /**
 | ||||
|  * Dictionnaire associant les types d'objets | ||||
|  * à des instances qui seront utilisées pour la | ||||
|  * construction d'autres objets de ces types | ||||
|  */ | ||||
| std::map<unsigned int, std::function<std::shared_ptr<Object>(std::ifstream&)>> object_type_map = { | ||||
|     {Player::TYPE_ID, Player::load}, | ||||
|     {Block::TYPE_ID, Block::load} | ||||
| }; | ||||
| 
 | ||||
| Level::Level(Manager& manager) : View(manager) {} | ||||
| Level::~Level() { | ||||
|     objects.clear(); | ||||
| } | ||||
| 
 | ||||
| void Level::load(std::ifstream& file) { | ||||
|     // vide le niveau précédent s'il y a lieu
 | ||||
|     if (objects.size() != 0) { | ||||
|         objects.clear(); | ||||
|     } | ||||
| 
 | ||||
|     // lecture de la signture du fichier ("BAR")
 | ||||
|     char signature[3]; | ||||
|     file.read(signature, sizeof(signature)); | ||||
| 
 | ||||
|     if (strncmp(signature, "BAR", sizeof(signature)) != 0) { | ||||
|         throw std::runtime_error( | ||||
|             "Impossible de lire le fichier : en-tête invalide" | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     // lecture de la version du fichier
 | ||||
|     char file_version; | ||||
|     file.read(&file_version, 1); | ||||
| 
 | ||||
|     if (file_version != 0) { | ||||
|         throw std::runtime_error( | ||||
|             "Impossible de lire le fichier : version non prise en charge" | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     // lecture du nom du niveau
 | ||||
|     std::getline(file, name, '\0'); | ||||
| 
 | ||||
|     // 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), sizeof(pos_x)); | ||||
|         file.read(reinterpret_cast<char*>(&pos_y), sizeof(pos_y)); | ||||
| 
 | ||||
|         pos_x *= Constants::GRID; | ||||
|         pos_y *= Constants::GRID; | ||||
| 
 | ||||
|         zone.push_back(std::make_pair(pos_x, pos_y)); | ||||
|     } | ||||
| 
 | ||||
|     // lecture des chemins de la musique et du fond
 | ||||
|     std::string music_name, background_name; | ||||
|     ResourceManager& resource_manager = manager.getResourceManager(); | ||||
| 
 | ||||
|     std::getline(file, music_name, '\0'); | ||||
|     resource_manager.setMusic(music_name); | ||||
|     resource_manager.playMusic(); | ||||
| 
 | ||||
|     std::getline(file, background_name, '\0'); | ||||
|     background.setTexture(resource_manager.getTexture(background_name)); | ||||
| 
 | ||||
|     // lecture du nombre de blocs
 | ||||
|     int 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); | ||||
| 
 | ||||
|         // vérifie que le type est pris en charge
 | ||||
|         // pour éviter une erreur de segmentation
 | ||||
|         if (object_type_map.count(block_type) == 0) { | ||||
|             throw std::runtime_error( | ||||
|                 "Impossible de lire le fichier : type d'objet inconnu" | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         objects.push_back(object_type_map[block_type](file)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Level::save() { | ||||
|     // TODO: faire une fonction d'enregistrement
 | ||||
| } | ||||
| 
 | ||||
| void Level::draw() { | ||||
|     // efface la scène précédente et dessine la couche de fond
 | ||||
|     sf::RenderWindow& window = manager.getWindow(); | ||||
|     window.clear(sf::Color(66, 165, 245)); | ||||
|     window.draw(background); | ||||
| 
 | ||||
|     // chargement de la file d'affichage des objets
 | ||||
|     std::priority_queue<ObjectPtr, std::vector<ObjectPtr>, ObjectCompare> display_queue; | ||||
| 
 | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         display_queue.push(objects[i]); | ||||
|     } | ||||
| 
 | ||||
|     // dessin des objets de la file d'affichage couche par couche
 | ||||
|     while (!display_queue.empty()) { | ||||
|         display_queue.top()->draw(manager); | ||||
|         display_queue.pop(); | ||||
|     } | ||||
| 
 | ||||
|     window.display(); | ||||
| } | ||||
| 
 | ||||
| std::string Level::getName() { | ||||
|     return name; | ||||
| } | ||||
| 
 | ||||
| std::vector<ObjectPtr> Level::getObjects() { | ||||
|     return objects; | ||||
| } | ||||
| 
 | ||||
| std::vector<std::pair<float, float>> Level::getZone() { | ||||
|     return zone; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue