Centralisation de l'état dans un gestionnaire principal
Démarrage de l'abstraction nécessaire à l'utilisation de plusieurs vues
This commit is contained in:
		
							parent
							
								
									c505437e01
								
							
						
					
					
						commit
						dde1280573
					
				|  | @ -3,11 +3,10 @@ | |||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| #include "object.hpp" | ||||
| #include "engine_state.hpp" | ||||
| 
 | ||||
| class Block : public Object { | ||||
| private: | ||||
|     sf::Sprite sprite; | ||||
|     mutable sf::Sprite sprite; | ||||
| 
 | ||||
| public: | ||||
|     Block(float x, float y); | ||||
|  | @ -15,18 +14,18 @@ public: | |||
|     /**
 | ||||
|      * Dessin du bloc dans la fenêtre donnée | ||||
|      */ | ||||
|     virtual void draw(sf::RenderWindow& window, ResourceManager& resources); | ||||
|     virtual void draw(Manager& manager); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère la boîte englobante de l'objet | ||||
|      */ | ||||
|     std::unique_ptr<sf::FloatRect> getAABB(); | ||||
|     virtual std::unique_ptr<sf::FloatRect> getAABB() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère l'identifiant de type de cet objet | ||||
|      */ | ||||
|     static constexpr unsigned int TYPE_ID = 1; | ||||
|     unsigned int getTypeId(); | ||||
|     virtual unsigned int getTypeId() const; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -1,26 +0,0 @@ | |||
| #ifndef __PTF_ENGINE_STATE_HPP__ | ||||
| #define __PTF_ENGINE_STATE_HPP__ | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <array> | ||||
| 
 | ||||
| // pré-déclaration de Object pour éviter les erreurs
 | ||||
| // de compilation Object est définie dans object.hpp
 | ||||
| class Object; | ||||
| 
 | ||||
| /**
 | ||||
|  * Structure qui retient l'état actuel du moteur | ||||
|  * Cette structure est passée aux objets pour qu'ils se | ||||
|  * mettent à jour en fonction de cet état | ||||
|  */ | ||||
| struct EngineState { | ||||
|     std::vector<Object*> objects; | ||||
|     std::array<bool, sf::Keyboard::KeyCount> keys; | ||||
| 
 | ||||
|     EngineState() { | ||||
|         // aucune touche n'est enfoncée au démarrage
 | ||||
|         keys.fill(false); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  | @ -1,44 +1,43 @@ | |||
| #ifndef __PTF_GAME_HPP__ | ||||
| #define __PTF_GAME_HPP__ | ||||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| #include <SFML/Audio.hpp> | ||||
| #include "view.hpp" | ||||
| #include "object.hpp" | ||||
| #include "engine_state.hpp" | ||||
| #include "manager.hpp" | ||||
| #include "resource_manager.hpp" | ||||
| 
 | ||||
| /**
 | ||||
|  * La classe Game gère l'affichage et les objets | ||||
|  * d'une partie de jeu | ||||
|  */ | ||||
| class Game { | ||||
| class Game : public View { | ||||
| private: | ||||
|     sf::Clock clock; | ||||
|     sf::RenderWindow window; | ||||
|     sf::View view; | ||||
|     sf::Music music; | ||||
| 
 | ||||
|     EngineState state; | ||||
|     ResourceManager resources; | ||||
|     float accumulator; | ||||
|     std::vector<Object*> objects; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Met à jour les objets du jeu pour | ||||
|      * qu'ils s'adaptent au nouvel état | ||||
|      */ | ||||
|     void update(); | ||||
|     void update(const Manager& manager); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Dessine la scène du jeu couche par couche | ||||
|      */ | ||||
|     void draw(); | ||||
|     void draw(Manager& manager); | ||||
| 
 | ||||
| public: | ||||
|     Game(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Démarre la boucle principale du jeu | ||||
|      * Demande le passage à la frame suivante sur | ||||
|      * cette vue | ||||
|      */ | ||||
|     void start(); | ||||
|     void frame(Manager& manager); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Ajoute un nouvel objet à la liste des objets du jeu | ||||
|  |  | |||
|  | @ -0,0 +1,54 @@ | |||
| #ifndef __PTF_MANAGER_HPP__ | ||||
| #define __PTF_MANAGER_HPP__ | ||||
| 
 | ||||
| #include "resource_manager.hpp" | ||||
| #include "view.hpp" | ||||
| 
 | ||||
| /**
 | ||||
|  * Gestionnaire principal de toutes les vues et | ||||
|  * ressources du jeu | ||||
|  */ | ||||
| class Manager { | ||||
| private: | ||||
|     sf::RenderWindow window; | ||||
|     sf::Clock clock; | ||||
| 
 | ||||
|     float elapsed_time; | ||||
|     ResourceManager resource_manager; | ||||
|     std::array<bool, sf::Keyboard::KeyCount> keys; | ||||
| 
 | ||||
| public: | ||||
|     // FIXME: devrait être privé
 | ||||
|     View* view; | ||||
| 
 | ||||
|     Manager(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Démarre la boucle principale du jeu | ||||
|      */ | ||||
|     void start(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie la fenêtre actuellement utilisée pour le dessin | ||||
|      */ | ||||
|     sf::RenderWindow& getWindow(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie le temps écoulé entre la frame précédente | ||||
|      * et la frame actuelle | ||||
|      */ | ||||
|     float getElapsedTime() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie le gestionnaire de ressources | ||||
|      */ | ||||
|     ResourceManager& getResourceManager(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie un booléen attestant de l'appui sur la | ||||
|      * touche donnée ou non | ||||
|      */ | ||||
|     bool isKeyPressed(sf::Keyboard::Key key) const; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  | @ -3,13 +3,10 @@ | |||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| #include <memory> | ||||
| #include "engine_state.hpp" | ||||
| #include "collision_data.hpp" | ||||
| #include "manager.hpp" | ||||
| #include "resource_manager.hpp" | ||||
| 
 | ||||
| class Block; | ||||
| class Player; | ||||
| 
 | ||||
| class Object { | ||||
| private: | ||||
|     sf::Vector2f acceleration; | ||||
|  | @ -20,7 +17,7 @@ private: | |||
|     sf::VertexArray velocity_line; | ||||
| 
 | ||||
|     float mass; | ||||
|     float inv_mass; | ||||
|     mutable float inv_mass; | ||||
|     float charge; | ||||
|     float restitution; | ||||
|     float static_friction; | ||||
|  | @ -31,7 +28,7 @@ protected: | |||
|     /**
 | ||||
|      * Calcule les forces appliquées à l'objet | ||||
|      */ | ||||
|     virtual sf::Vector2f getForces(EngineState& state); | ||||
|     virtual sf::Vector2f getForces(const Manager& manager, const std::vector<Object*>& objects) const; | ||||
| 
 | ||||
| public: | ||||
|     Object(float x, float y); | ||||
|  | @ -39,32 +36,32 @@ public: | |||
|     /**
 | ||||
|      * Dessine l'objet dans la fenêtre donnée | ||||
|      */ | ||||
|     virtual void draw(sf::RenderWindow& window, ResourceManager& resources); | ||||
|     virtual void draw(Manager& manager); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Met à jour la vitesse de l'objet selon les | ||||
|      * forces qui lui sont appliquées | ||||
|      */ | ||||
|     void updateVelocity(EngineState& state, float delta); | ||||
|     void updateVelocity(const Manager& manager, const std::vector<Object*>& objects, float delta); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Met à jour la position de l'objet selon sa | ||||
|      * vitesse actuelle | ||||
|      */ | ||||
|     void updatePosition(EngineState& state, float delta); | ||||
|     void updatePosition(float delta); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Détecte s'il y a collision entre cet objet | ||||
|      * et l'objet passé en paramètre | ||||
|      */ | ||||
|     bool detectCollision(Object& obj, CollisionData& data); | ||||
|     bool detectCollision(const Object& obj, CollisionData& data) const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Résolution de la collision entre cet objet | ||||
|      * et l'objet passé en paramètre selon la normale | ||||
|      * donnée | ||||
|      */ | ||||
|     void solveCollision(Object& obj, sf::Vector2f normal); | ||||
|     void solveCollision(Object& obj, const sf::Vector2f& normal); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Application de la correction positionnelle sur | ||||
|  | @ -74,27 +71,27 @@ public: | |||
|      * les objets peuvent accumuler une erreur de positionnement | ||||
|      * qui les fait "plonger" les uns dans les autres | ||||
|      */ | ||||
|     void positionalCorrection(Object& obj, sf::Vector2f normal, float depth); | ||||
|     void positionalCorrection(Object& obj, const sf::Vector2f& normal, float depth); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère la boîte englobante de l'objet | ||||
|      */ | ||||
|     virtual std::unique_ptr<sf::FloatRect> getAABB() = 0; | ||||
|     virtual std::unique_ptr<sf::FloatRect> getAABB() const = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère l'identifiant de type de cet objet | ||||
|      */ | ||||
|     virtual unsigned int getTypeId() = 0; | ||||
|     virtual unsigned int getTypeId() const = 0; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère l'accélération de l'objet | ||||
|      */ | ||||
|     sf::Vector2f getAcceleration(); | ||||
|     sf::Vector2f getAcceleration() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère la vitesse de l'objet | ||||
|      */ | ||||
|     sf::Vector2f getVelocity(); | ||||
|     sf::Vector2f getVelocity() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie la vitesse de l'objet | ||||
|  | @ -105,7 +102,7 @@ public: | |||
|     /**
 | ||||
|      * Récupère la position de l'objet | ||||
|      */ | ||||
|     sf::Vector2f getPosition(); | ||||
|     sf::Vector2f getPosition() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie la position de l'objet | ||||
|  | @ -116,12 +113,12 @@ public: | |||
|     /**
 | ||||
|      * Récupère la masse de l'objet | ||||
|      */ | ||||
|     float getMass(); | ||||
|     float getMass() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère l'inverse de la masse de l'objet (en cache) | ||||
|      */ | ||||
|     float getMassInvert(); | ||||
|     float getMassInvert() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie la masse de l'objet | ||||
|  | @ -131,7 +128,7 @@ public: | |||
|     /**
 | ||||
|      * Récupère la charge de l'objet | ||||
|      */ | ||||
|     float getCharge(); | ||||
|     float getCharge() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie la charge de l'objet | ||||
|  | @ -141,7 +138,7 @@ public: | |||
|     /**
 | ||||
|      * Récupère le coefficient de restitution de l'objet | ||||
|      */ | ||||
|     float getRestitution(); | ||||
|     float getRestitution() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie le coefficient de restitution de l'objet | ||||
|  | @ -151,7 +148,7 @@ public: | |||
|     /**
 | ||||
|      * Récupère le coefficient de frottement dynamique de l'objet | ||||
|      */ | ||||
|     float getStaticFriction(); | ||||
|     float getStaticFriction() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie le coefficient de frottement dynamique de l'objet | ||||
|  | @ -161,7 +158,7 @@ public: | |||
|     /**
 | ||||
|      * Récupère le coefficient de frottement dynamique de l'objet | ||||
|      */ | ||||
|     float getDynamicFriction(); | ||||
|     float getDynamicFriction() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie le coefficient de frottement dynamique de l'objet | ||||
|  | @ -171,12 +168,12 @@ public: | |||
|     /**
 | ||||
|      * Récupère la couche d'affichage de l'objet | ||||
|      */ | ||||
|     unsigned int getLayer(); | ||||
|     int getLayer() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie la couche d'affichage de l'objet | ||||
|      */ | ||||
|     void setLayer(unsigned int set_layer); | ||||
|     void setLayer(int set_layer); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -185,7 +182,7 @@ public: | |||
|  * qui doit être dessinée avant celle du second | ||||
|  */ | ||||
| struct ObjectCompare { | ||||
| 	bool operator()(Object* const &t1, Object* const &t2); | ||||
| 	bool operator()(Object* const &t1, Object* const &t2) const; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -3,18 +3,17 @@ | |||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| #include "object.hpp" | ||||
| #include "engine_state.hpp" | ||||
| 
 | ||||
| class Player : public Object { | ||||
| private: | ||||
|     sf::Sprite sprite; | ||||
|     mutable sf::Sprite sprite; | ||||
|     unsigned int player_number; | ||||
| 
 | ||||
| protected: | ||||
|     /**
 | ||||
|      * Calcule les forces appliquées à l'objet | ||||
|      */ | ||||
|     virtual sf::Vector2f getForces(EngineState& state); | ||||
|     virtual sf::Vector2f getForces(const Manager& manager, const std::vector<Object*>& objects) const; | ||||
| 
 | ||||
| public: | ||||
|     Player(float x, float y); | ||||
|  | @ -22,28 +21,28 @@ public: | |||
|     /**
 | ||||
|      * Dessine la balle dans la fenêtre donnée | ||||
|      */ | ||||
|     virtual void draw(sf::RenderWindow& window, ResourceManager& resources); | ||||
|     virtual void draw(Manager& manager); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère la boîte englobante de l'objet | ||||
|      */ | ||||
|     std::unique_ptr<sf::FloatRect> getAABB(); | ||||
|     virtual std::unique_ptr<sf::FloatRect> getAABB() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Récupère l'identifiant de type de cet objet | ||||
|      */ | ||||
|     static constexpr unsigned int TYPE_ID = 0; | ||||
|     unsigned int getTypeId(); | ||||
|     virtual unsigned int getTypeId() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie le rayon de la balle | ||||
|      */ | ||||
|     float getRadius(); | ||||
|     float getRadius() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Renvoie le numéro du joueur | ||||
|      */ | ||||
|     unsigned int getPlayerNumber(); | ||||
|     unsigned int getPlayerNumber() const; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Modifie le numéro du joueur | ||||
|  |  | |||
|  | @ -0,0 +1,23 @@ | |||
| #ifndef __PTF_VIEW_HPP__ | ||||
| #define __PTF_VIEW_HPP__ | ||||
| 
 | ||||
| #include <SFML/Graphics.hpp> | ||||
| 
 | ||||
| class Manager; | ||||
| class Object; | ||||
| 
 | ||||
| /**
 | ||||
|  * Classe abstraite pour les vues | ||||
|  */ | ||||
| class View { | ||||
| public: | ||||
|     /**
 | ||||
|      * Demande le passage à la frame suivante sur | ||||
|      * cette vue | ||||
|      */ | ||||
|     virtual void frame(Manager& manager) = 0; | ||||
| 
 | ||||
|     virtual void addObject(Object& object) = 0; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
|  | @ -12,11 +12,13 @@ Block::Block(float x, float y) : Object(x, y) { | |||
|     sprite.setOrigin(sf::Vector2f(Constants::GRID / 2, Constants::GRID / 2)); | ||||
| } | ||||
| 
 | ||||
| void Block::draw(sf::RenderWindow& window, ResourceManager& resources) { | ||||
|     Object::draw(window, resources); | ||||
| void Block::draw(Manager& manager) { | ||||
|     Object::draw(manager); | ||||
| 
 | ||||
|     // utilisation de la texture
 | ||||
|     sprite.setTexture(resources.getTexture("block.png")); | ||||
|     sprite.setTexture( | ||||
|         manager.getResourceManager().getTexture("block.png") | ||||
|     ); | ||||
| 
 | ||||
|     // coloration du bloc en fonction de sa charge
 | ||||
|     if (getCharge() > 0) { | ||||
|  | @ -28,10 +30,10 @@ void Block::draw(sf::RenderWindow& window, ResourceManager& resources) { | |||
|     } | ||||
| 
 | ||||
|     sprite.setPosition(getPosition()); | ||||
|     window.draw(sprite); | ||||
|     manager.getWindow().draw(sprite); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<sf::FloatRect> Block::getAABB() { | ||||
| std::unique_ptr<sf::FloatRect> Block::getAABB() const { | ||||
|     return std::unique_ptr<sf::FloatRect>(new sf::FloatRect( | ||||
|         getPosition().x - Constants::GRID / 2, | ||||
|         getPosition().y - Constants::GRID / 2, | ||||
|  | @ -39,6 +41,6 @@ std::unique_ptr<sf::FloatRect> Block::getAABB() { | |||
|     )); | ||||
| } | ||||
| 
 | ||||
| unsigned int Block::getTypeId() { | ||||
| unsigned int Block::getTypeId() const { | ||||
|     return Block::TYPE_ID; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										108
									
								
								src/game.cpp
								
								
								
								
							
							
						
						
									
										108
									
								
								src/game.cpp
								
								
								
								
							|  | @ -3,82 +3,42 @@ | |||
| #include <cmath> | ||||
| #include <queue> | ||||
| 
 | ||||
| Game::Game() : window( | ||||
|     sf::VideoMode(704, 480), "Projet CMI", sf::Style::Default, | ||||
|     sf::ContextSettings(0, 0, 2) | ||||
| ), view(sf::FloatRect(0, 0, 704, 480)) { | ||||
|     window.setVerticalSyncEnabled(true); | ||||
| 
 | ||||
|     // mise en place de la caméra
 | ||||
|     view.setSize(704, 480); | ||||
|     window.setView(view); | ||||
| } | ||||
| 
 | ||||
| void Game::start() { | ||||
|     float accumulator = 0; | ||||
|     if (!music.openFromFile("./res/music_lvl1.wav")) | ||||
|     { | ||||
| Game::Game() : accumulator(0.f) { | ||||
|     if (!music.openFromFile("./res/music_lvl1.wav")) { | ||||
|         // erreur
 | ||||
|     } | ||||
| 
 | ||||
|     music.play(); | ||||
|     music.setVolume(15); | ||||
|     music.setLoop(true); | ||||
| 
 | ||||
|     // boucle d'événements sur la fenêtre
 | ||||
|     while (window.isOpen()) { | ||||
|         sf::Event event; | ||||
| 
 | ||||
|         // traitement des évènements reçus
 | ||||
|         while (window.pollEvent(event)) { | ||||
|             // fermeture de la fenêtre
 | ||||
|             if (event.type == sf::Event::Closed) { | ||||
|                 window.close(); | ||||
|             } | ||||
| 
 | ||||
|             // suivi de l'enfoncement et du relâchement des touches
 | ||||
|             if (event.type == sf::Event::KeyPressed) { | ||||
|                 state.keys[event.key.code] = true; | ||||
|             } | ||||
| 
 | ||||
|             if (event.type == sf::Event::KeyReleased) { | ||||
|                 state.keys[event.key.code] = false; | ||||
|             } | ||||
| 
 | ||||
| 			// lorsque la fenêtre est redimensionnée par l'utilisateur,
 | ||||
|             // mise à jour de la caméra en fonction de la taille de la fenêtre
 | ||||
|     		if (event.type == sf::Event::Resized) { | ||||
|                 sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); | ||||
|                 window.setView(sf::View(visibleArea)); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         float frame = clock.restart().asSeconds(); | ||||
|         accumulator += frame; | ||||
| 
 | ||||
|         // tant qu'il reste du temps à passer,
 | ||||
|         // effectuer la simulation physique étape par étape
 | ||||
|         while (accumulator >= Constants::PHYSICS_TIME) { | ||||
|             accumulator -= Constants::PHYSICS_TIME; | ||||
|             update(); | ||||
|         } | ||||
| 
 | ||||
|         draw(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Game::addObject(Object& object) { | ||||
|     state.objects.push_back(&object); | ||||
|     objects.push_back(&object); | ||||
| } | ||||
| 
 | ||||
| void Game::update() { | ||||
| void Game::frame(Manager& manager) { | ||||
|     accumulator += manager.getElapsedTime(); | ||||
| 
 | ||||
|     // tant qu'il reste du temps à passer,
 | ||||
|     // effectuer la simulation physique étape par étape
 | ||||
|     while (accumulator >= Constants::PHYSICS_TIME) { | ||||
|         accumulator -= Constants::PHYSICS_TIME; | ||||
|         update(manager); | ||||
|     } | ||||
| 
 | ||||
|     draw(manager); | ||||
| } | ||||
| 
 | ||||
| void Game::update(const Manager& manager) { | ||||
|     std::vector<CollisionData> colliding; | ||||
| 
 | ||||
|     // détection des objets en collision
 | ||||
|     for (unsigned int i = 0; i < state.objects.size(); i++) { | ||||
|         Object* objA = state.objects[i]; | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         Object* objA = objects[i]; | ||||
| 
 | ||||
|         for (unsigned int j = i + 1; j < state.objects.size(); j++) { | ||||
|             Object* objB = state.objects[j]; | ||||
|         for (unsigned int j = i + 1; j < objects.size(); j++) { | ||||
|             Object* objB = objects[j]; | ||||
|             CollisionData data(*objA, *objB); | ||||
| 
 | ||||
|             if (objA->detectCollision(*objB, data)) { | ||||
|  | @ -88,8 +48,8 @@ void Game::update() { | |||
|     } | ||||
| 
 | ||||
|     // intégration des forces dans la vitesse (première moitié)
 | ||||
|     for (unsigned int i = 0; i < state.objects.size(); i++) { | ||||
|         state.objects[i]->updateVelocity(state, Constants::PHYSICS_TIME / 2); | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         objects[i]->updateVelocity(manager, objects, Constants::PHYSICS_TIME / 2); | ||||
|     } | ||||
| 
 | ||||
|     // résolution des collisions détectées
 | ||||
|  | @ -99,8 +59,8 @@ void Game::update() { | |||
|     } | ||||
| 
 | ||||
|     // intégration de la vitesse dans la position
 | ||||
|     for (unsigned int i = 0; i < state.objects.size(); i++) { | ||||
|         state.objects[i]->updatePosition(state, Constants::PHYSICS_TIME); | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         objects[i]->updatePosition(Constants::PHYSICS_TIME); | ||||
|     } | ||||
| 
 | ||||
|     // application de la correction positionnelle
 | ||||
|  | @ -112,27 +72,27 @@ void Game::update() { | |||
|     } | ||||
| 
 | ||||
|     // intégration des forces dans la vitesse (seconde moitié)
 | ||||
|     for (unsigned int i = 0; i < state.objects.size(); i++) { | ||||
|         state.objects[i]->updateVelocity(state, Constants::PHYSICS_TIME / 2); | ||||
|     for (unsigned int i = 0; i < objects.size(); i++) { | ||||
|         objects[i]->updateVelocity(manager, objects, Constants::PHYSICS_TIME / 2); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Game::draw() { | ||||
| void Game::draw(Manager& manager) { | ||||
|     // efface la scène précédente et dessine la couche de fond
 | ||||
|     window.clear(sf::Color(66, 165, 245)); | ||||
|     manager.getWindow().clear(sf::Color(66, 165, 245)); | ||||
| 
 | ||||
|     // chargement de la file d'affichage des objets
 | ||||
|     std::priority_queue<Object*, std::vector<Object*>, ObjectCompare> display_queue; | ||||
| 
 | ||||
|     for (unsigned int i = 0; i < state.objects.size(); i++) { | ||||
|         display_queue.push(state.objects[i]); | ||||
|     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(window, resources); | ||||
|         display_queue.top()->draw(manager); | ||||
|         display_queue.pop(); | ||||
|     } | ||||
| 
 | ||||
|     window.display(); | ||||
|     manager.getWindow().display(); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										56
									
								
								src/main.cpp
								
								
								
								
							
							
						
						
									
										56
									
								
								src/main.cpp
								
								
								
								
							|  | @ -1,12 +1,13 @@ | |||
| #include "player.hpp" | ||||
| #include "block.hpp" | ||||
| #include "manager.hpp" | ||||
| #include "game.hpp" | ||||
| #include "constants.hpp" | ||||
| #include <cstdlib> | ||||
| #include <iostream> | ||||
| 
 | ||||
| int main() { | ||||
|     Game game; | ||||
|     Manager manager; | ||||
| 
 | ||||
|     Player player1(3.5f * Constants::GRID, 10 * Constants::GRID); | ||||
|     player1.setPlayerNumber(1); | ||||
|  | @ -40,33 +41,36 @@ int main() { | |||
|     block22.setCharge(1.f); | ||||
|     block22.setMass(2); | ||||
| 
 | ||||
|     game.addObject(player1); | ||||
|     game.addObject(player2); | ||||
|     game.addObject(block01); | ||||
|     game.addObject(block02); | ||||
|     game.addObject(block03); | ||||
|     game.addObject(block04); | ||||
|     game.addObject(block05); | ||||
|     game.addObject(block06); | ||||
|     game.addObject(block07); | ||||
|     game.addObject(block08); | ||||
|     game.addObject(block09); | ||||
|     game.addObject(block10); | ||||
|     game.addObject(block11); | ||||
|     game.addObject(block12); | ||||
|     game.addObject(block13); | ||||
|     game.addObject(block14); | ||||
|     game.addObject(block15); | ||||
|     game.addObject(block16); | ||||
|     game.addObject(block17); | ||||
|     game.addObject(block18); | ||||
|     game.addObject(block19); | ||||
|     game.addObject(block20); | ||||
|     game.addObject(block21); | ||||
|     game.addObject(block22); | ||||
|     Game game_view; | ||||
|     manager.view = &game_view; | ||||
| 
 | ||||
|     manager.view->addObject(player1); | ||||
|     manager.view->addObject(player2); | ||||
|     manager.view->addObject(block01); | ||||
|     manager.view->addObject(block02); | ||||
|     manager.view->addObject(block03); | ||||
|     manager.view->addObject(block04); | ||||
|     manager.view->addObject(block05); | ||||
|     manager.view->addObject(block06); | ||||
|     manager.view->addObject(block07); | ||||
|     manager.view->addObject(block08); | ||||
|     manager.view->addObject(block09); | ||||
|     manager.view->addObject(block10); | ||||
|     manager.view->addObject(block11); | ||||
|     manager.view->addObject(block12); | ||||
|     manager.view->addObject(block13); | ||||
|     manager.view->addObject(block14); | ||||
|     manager.view->addObject(block15); | ||||
|     manager.view->addObject(block16); | ||||
|     manager.view->addObject(block17); | ||||
|     manager.view->addObject(block18); | ||||
|     manager.view->addObject(block19); | ||||
|     manager.view->addObject(block20); | ||||
|     manager.view->addObject(block21); | ||||
|     manager.view->addObject(block22); | ||||
| 
 | ||||
|     try { | ||||
|         game.start(); | ||||
|         manager.start(); | ||||
|     } catch (const std::exception& exception) { | ||||
|         std::cerr << std::endl; | ||||
|         std::cerr << "Le programme a quitté après une erreur d'exécution." << std::endl; | ||||
|  |  | |||
|  | @ -0,0 +1,57 @@ | |||
| #include "manager.hpp" | ||||
| 
 | ||||
| Manager::Manager() : window( | ||||
|     sf::VideoMode(704, 480), "Projet CMI", sf::Style::Default, | ||||
|     sf::ContextSettings(0, 0, 2) | ||||
| ), elapsed_time(0.f), view(NULL) { | ||||
|     keys.fill(false); | ||||
| } | ||||
| 
 | ||||
| void Manager::start() { | ||||
|     while (window.isOpen()) { | ||||
|         sf::Event event; | ||||
| 
 | ||||
|         // traitement des évènements reçus
 | ||||
|         while (window.pollEvent(event)) { | ||||
|             // fermeture de la fenêtre
 | ||||
|             if (event.type == sf::Event::Closed) { | ||||
|                 window.close(); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // suivi de l'enfoncement et du relâchement des touches
 | ||||
|             if (event.type == sf::Event::KeyPressed) { | ||||
|                 keys[event.key.code] = true; | ||||
|             } | ||||
| 
 | ||||
|             if (event.type == sf::Event::KeyReleased) { | ||||
|                 keys[event.key.code] = false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // demande à la vue de se mettre à jour sur
 | ||||
|         // la prochaine frame
 | ||||
|         if (view == NULL) { | ||||
|             throw std::runtime_error("Aucune vue à afficher pour le jeu"); | ||||
|         } | ||||
| 
 | ||||
|         elapsed_time = clock.restart().asSeconds(); | ||||
|         view->frame(*this); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| sf::RenderWindow& Manager::getWindow() { | ||||
|     return window; | ||||
| } | ||||
| 
 | ||||
| float Manager::getElapsedTime() const { | ||||
|     return elapsed_time; | ||||
| } | ||||
| 
 | ||||
| ResourceManager& Manager::getResourceManager() { | ||||
|     return resource_manager; | ||||
| } | ||||
| 
 | ||||
| bool Manager::isKeyPressed(sf::Keyboard::Key key) const { | ||||
|     return keys[key]; | ||||
| } | ||||
|  | @ -15,7 +15,9 @@ Object::Object(float x, float y) : | |||
|     dynamic_friction(0.2f), | ||||
|     layer(Constants::DEFAULT_LAYER) {} | ||||
| 
 | ||||
| sf::Vector2f Object::getForces(EngineState& state) { | ||||
| sf::Vector2f Object::getForces( | ||||
|     const Manager& manager, const std::vector<Object*>& objects | ||||
| ) const { | ||||
|     sf::Vector2f forces(0, 0); | ||||
| 
 | ||||
|     // force de gravité
 | ||||
|  | @ -23,8 +25,8 @@ sf::Vector2f Object::getForces(EngineState& state) { | |||
| 
 | ||||
|     // force d'attraction entre objets chargés
 | ||||
|     if (getCharge() != 0) { | ||||
|         for (unsigned int j = 0; j < state.objects.size(); j++) { | ||||
|             Object *attractive = state.objects[j]; | ||||
|         for (unsigned int j = 0; j < objects.size(); j++) { | ||||
|             Object *attractive = objects[j]; | ||||
| 
 | ||||
|             if (attractive == this || attractive->getCharge() == 0) { | ||||
|                 continue; | ||||
|  | @ -57,7 +59,7 @@ sf::Vector2f Object::getForces(EngineState& state) { | |||
|     return forces; | ||||
| } | ||||
| 
 | ||||
| void Object::draw(sf::RenderWindow& window, ResourceManager& resources) { | ||||
| void Object::draw(Manager& manager) { | ||||
|     if (Constants::DEBUG_MODE) { | ||||
|         velocity_line[0].position = position; | ||||
|         velocity_line[0].color = sf::Color::Green; | ||||
|  | @ -69,21 +71,23 @@ void Object::draw(sf::RenderWindow& window, ResourceManager& resources) { | |||
|         acceleration_line[1].position = position + acceleration * 1.f; | ||||
|         acceleration_line[1].color = sf::Color::Red; | ||||
| 
 | ||||
|         window.draw(velocity_line); | ||||
|         window.draw(acceleration_line); | ||||
|         manager.getWindow().draw(velocity_line); | ||||
|         manager.getWindow().draw(acceleration_line); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Object::updateVelocity(EngineState& state, float delta) { | ||||
|     acceleration = getForces(state) * getMassInvert(); | ||||
| void Object::updateVelocity( | ||||
|     const Manager& manager, const std::vector<Object*>& objects, float delta | ||||
| ) { | ||||
|     acceleration = getForces(manager, objects) * getMassInvert(); | ||||
|     velocity += acceleration * delta; | ||||
| } | ||||
| 
 | ||||
| void Object::updatePosition(EngineState& state, float delta) { | ||||
| void Object::updatePosition(float delta) { | ||||
|     position += velocity * delta; | ||||
| } | ||||
| 
 | ||||
| bool Object::detectCollision(Object& obj, CollisionData& data) { | ||||
| bool Object::detectCollision(const Object& obj, CollisionData& data) const { | ||||
|     // si les objets ne sont pas sur la même couche,
 | ||||
|     // ils ne peuvent pas entrer en collision
 | ||||
|     if (getLayer() != obj.getLayer()) { | ||||
|  | @ -103,7 +107,7 @@ bool Object::detectCollision(Object& obj, CollisionData& data) { | |||
|     ](data); | ||||
| } | ||||
| 
 | ||||
| void Object::solveCollision(Object& obj, sf::Vector2f normal) { | ||||
| void Object::solveCollision(Object& obj, const sf::Vector2f& normal) { | ||||
|     // si les deux objets sont de masse infinie, réinitialisation
 | ||||
|     // des vitesses en tant que collision
 | ||||
|     if (getMassInvert() == 0 && obj.getMassInvert() == 0) { | ||||
|  | @ -164,7 +168,7 @@ void Object::solveCollision(Object& obj, sf::Vector2f normal) { | |||
|     obj.setVelocity(obj.getVelocity() + obj.getMassInvert() * friction_impulse * tangent); | ||||
| } | ||||
| 
 | ||||
| void Object::positionalCorrection(Object& obj, sf::Vector2f normal, float depth) { | ||||
| void Object::positionalCorrection(Object& obj, const sf::Vector2f& normal, float depth) { | ||||
|     // ne pas corriger les petites erreurs de position
 | ||||
|     // pour éviter l'instabilité du moteur
 | ||||
|     if (depth <= Constants::CORRECTION_THRESHOLD) { | ||||
|  | @ -178,11 +182,11 @@ void Object::positionalCorrection(Object& obj, sf::Vector2f normal, float depth) | |||
|     obj.setPosition(obj.getPosition() + obj.getMassInvert() * position_correction * normal); | ||||
| } | ||||
| 
 | ||||
| sf::Vector2f Object::getAcceleration() { | ||||
| sf::Vector2f Object::getAcceleration() const { | ||||
|     return acceleration; | ||||
| } | ||||
| 
 | ||||
| sf::Vector2f Object::getVelocity() { | ||||
| sf::Vector2f Object::getVelocity() const { | ||||
|     return velocity; | ||||
| } | ||||
| 
 | ||||
|  | @ -190,7 +194,7 @@ void Object::setVelocity(sf::Vector2f set_velocity) { | |||
|     velocity = set_velocity; | ||||
| } | ||||
| 
 | ||||
| sf::Vector2f Object::getPosition() { | ||||
| sf::Vector2f Object::getPosition() const { | ||||
|     return position; | ||||
| } | ||||
| 
 | ||||
|  | @ -198,11 +202,11 @@ void Object::setPosition(sf::Vector2f set_position) { | |||
|     position = set_position; | ||||
| } | ||||
| 
 | ||||
| float Object::getMass() { | ||||
| float Object::getMass() const { | ||||
|     return mass; | ||||
| } | ||||
| 
 | ||||
| float Object::getMassInvert() { | ||||
| float Object::getMassInvert() const { | ||||
|     if (inv_mass >= 0) { | ||||
|         return inv_mass; | ||||
|     } | ||||
|  | @ -221,7 +225,7 @@ void Object::setMass(float set_mass) { | |||
|     inv_mass = -1.f; | ||||
| } | ||||
| 
 | ||||
| float Object::getCharge() { | ||||
| float Object::getCharge() const { | ||||
|     return charge; | ||||
| } | ||||
| 
 | ||||
|  | @ -229,7 +233,7 @@ void Object::setCharge(float set_charge) { | |||
|     charge = set_charge; | ||||
| } | ||||
| 
 | ||||
| float Object::getRestitution() { | ||||
| float Object::getRestitution() const { | ||||
|     return restitution; | ||||
| } | ||||
| 
 | ||||
|  | @ -237,7 +241,7 @@ void Object::setRestitution(float set_restitution) { | |||
|     restitution = set_restitution; | ||||
| } | ||||
| 
 | ||||
| float Object::getStaticFriction() { | ||||
| float Object::getStaticFriction() const { | ||||
|     return static_friction; | ||||
| } | ||||
| 
 | ||||
|  | @ -245,7 +249,7 @@ void Object::setStaticFriction(float set_static_friction) { | |||
|     static_friction = set_static_friction; | ||||
| } | ||||
| 
 | ||||
| float Object::getDynamicFriction() { | ||||
| float Object::getDynamicFriction() const { | ||||
|     return dynamic_friction; | ||||
| } | ||||
| 
 | ||||
|  | @ -253,14 +257,14 @@ void Object::setDynamicFriction(float set_dynamic_friction) { | |||
|     dynamic_friction = set_dynamic_friction; | ||||
| } | ||||
| 
 | ||||
| unsigned int Object::getLayer() { | ||||
| int Object::getLayer() const { | ||||
|     return layer; | ||||
| } | ||||
| 
 | ||||
| void Object::setLayer(unsigned int set_layer) { | ||||
| void Object::setLayer(int set_layer) { | ||||
|     layer = set_layer; | ||||
| } | ||||
| 
 | ||||
| bool ObjectCompare::operator()(Object* const &t1, Object* const &t2) { | ||||
| bool ObjectCompare::operator()(Object* const &t1, Object* const &t2) const { | ||||
|     return t1->getLayer() > t2->getLayer(); | ||||
| } | ||||
|  |  | |||
|  | @ -9,26 +9,26 @@ Player::Player(float x, float y) : Object(x, y) { | |||
|     sprite.setOrigin(sf::Vector2f(getRadius(), getRadius())); | ||||
| } | ||||
| 
 | ||||
| sf::Vector2f Player::getForces(EngineState& state) { | ||||
|     sf::Vector2f forces = Object::getForces(state); | ||||
| sf::Vector2f Player::getForces(const Manager& manager, const std::vector<Object*>& objects) const { | ||||
|     sf::Vector2f forces = Object::getForces(manager, objects); | ||||
| 
 | ||||
|     // déplacement de la balle après appui sur les touches de direction
 | ||||
|     if (getPlayerNumber() == 1) { | ||||
|         if (state.keys[sf::Keyboard::Left]) { | ||||
|         if (manager.isKeyPressed(sf::Keyboard::Left)) { | ||||
|             forces += sf::Vector2f(-Constants::MOVE, 0); | ||||
|         } | ||||
| 
 | ||||
|         if (state.keys[sf::Keyboard::Right]) { | ||||
|         if (manager.isKeyPressed(sf::Keyboard::Right)) { | ||||
|             forces += sf::Vector2f(Constants::MOVE, 0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (getPlayerNumber() == 2) { | ||||
|         if (state.keys[sf::Keyboard::Q]) { | ||||
|         if (manager.isKeyPressed(sf::Keyboard::Q)) { | ||||
|             forces += sf::Vector2f(-Constants::MOVE, 0); | ||||
|         } | ||||
| 
 | ||||
|         if (state.keys[sf::Keyboard::D]) { | ||||
|         if (manager.isKeyPressed(sf::Keyboard::D)) { | ||||
|             forces += sf::Vector2f(Constants::MOVE, 0); | ||||
|         } | ||||
|     } | ||||
|  | @ -36,19 +36,21 @@ sf::Vector2f Player::getForces(EngineState& state) { | |||
|     return forces; | ||||
| } | ||||
| 
 | ||||
| void Player::draw(sf::RenderWindow& window, ResourceManager& resources) { | ||||
|     Object::draw(window, resources); | ||||
| void Player::draw(Manager& manager) { | ||||
|     Object::draw(manager); | ||||
| 
 | ||||
|     // utilisation de la texture
 | ||||
| 	sprite.setTexture(resources.getTexture("ball.png")); | ||||
| 	sprite.setTexture( | ||||
|         manager.getResourceManager().getTexture("ball.png") | ||||
|     ); | ||||
| 
 | ||||
|     // déplacement du sprite à la position de la balle
 | ||||
|     sprite.rotate(getVelocity().x * .1f); | ||||
|     sprite.rotate(getVelocity().x * Constants::PHYSICS_TIME * .5f); | ||||
|     sprite.setPosition(getPosition()); | ||||
|     window.draw(sprite); | ||||
|     manager.getWindow().draw(sprite); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<sf::FloatRect> Player::getAABB() { | ||||
| std::unique_ptr<sf::FloatRect> Player::getAABB() const { | ||||
|     return std::unique_ptr<sf::FloatRect>(new sf::FloatRect( | ||||
|         getPosition().x - getRadius(), | ||||
|         getPosition().y - getRadius(), | ||||
|  | @ -56,15 +58,15 @@ std::unique_ptr<sf::FloatRect> Player::getAABB() { | |||
|     )); | ||||
| } | ||||
| 
 | ||||
| unsigned int Player::getTypeId() { | ||||
| unsigned int Player::getTypeId() const { | ||||
|     return Player::TYPE_ID; | ||||
| } | ||||
| 
 | ||||
| float Player::getRadius() { | ||||
| float Player::getRadius() const { | ||||
|     return 10 * getMass(); | ||||
| } | ||||
| 
 | ||||
| unsigned int Player::getPlayerNumber() { | ||||
| unsigned int Player::getPlayerNumber() const { | ||||
|     return player_number; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue