From ca3d36bea8b3526846e21ad81aea46d25ee706ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre?= Date: Tue, 12 Apr 2016 18:11:36 +0200 Subject: [PATCH] Nettoyage du code (suppression #include inutiles, variables globales) --- .atom-build.json | 4 - include/block.hpp | 1 + include/constants.hpp | 27 ---- include/finish_block.hpp | 3 +- include/game.hpp | 3 +- include/gravity_block.hpp | 4 +- include/kill_block.hpp | 3 +- include/level.hpp | 4 +- include/manager.hpp | 8 +- include/menu.hpp | 3 +- include/object.hpp | 12 -- include/rules.hpp | 4 +- include/state.hpp | 1 - include/switch_block.hpp | 3 +- include/widget_button.hpp | 3 +- include/widget_timer.hpp | 3 +- include/widget_toolbar.hpp | 3 +- src/block.cpp | 13 +- src/collision.cpp | 284 +++++++++++++++++++------------------ src/editor.cpp | 27 ++-- src/finish_block.cpp | 1 + src/game.cpp | 2 +- src/gravity_block.cpp | 1 + src/kill_block.cpp | 1 + src/level.cpp | 246 ++++++++++++++++---------------- src/manager.cpp | 4 +- src/menu.cpp | 3 +- src/object.cpp | 101 ++++++++----- src/player.cpp | 6 +- src/resource_manager.cpp | 11 +- src/rules.cpp | 2 +- src/switch_block.cpp | 1 + src/widget_button.cpp | 15 +- src/widget_timer.cpp | 2 +- src/widget_toolbar.cpp | 10 +- 35 files changed, 425 insertions(+), 394 deletions(-) delete mode 100644 .atom-build.json delete mode 100644 include/constants.hpp diff --git a/.atom-build.json b/.atom-build.json deleted file mode 100644 index 986d574..0000000 --- a/.atom-build.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "cmd": "cd {PROJECT_PATH} && cmake {PROJECT_PATH} && make", - "name": "cmake" -} diff --git a/include/block.hpp b/include/block.hpp index 7554ff9..0b87328 100644 --- a/include/block.hpp +++ b/include/block.hpp @@ -6,6 +6,7 @@ #include "object.hpp" class Game; +class ResourceManager; class Level; class Block : public Object { diff --git a/include/constants.hpp b/include/constants.hpp deleted file mode 100644 index 88efc32..0000000 --- a/include/constants.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __SKIZZLE_CONSTANTS_HPP__ -#define __SKIZZLE_CONSTANTS_HPP__ - -#include - -namespace Constants { - /** - * Constante d'attraction. Utilisée dans la formule - * pour le calcul de l'attraction coulombienne entre - * deux objets - */ - static const float ATTRACTION = 500000; - - /** - * Correction positionnelle : pourcentage de correction - * et seuil de correction - */ - static const float CORRECTION_PERCENTAGE = .5f; - static const float CORRECTION_SLOP = .02f; - - /** - * Taille de la grille des blocs en pixels - */ - static const float GRID = 32; -} - -#endif diff --git a/include/finish_block.hpp b/include/finish_block.hpp index 8127ec1..8ec6f8f 100644 --- a/include/finish_block.hpp +++ b/include/finish_block.hpp @@ -4,7 +4,8 @@ #include #include #include "block.hpp" -#include "game.hpp" + +class Game; class FinishBlock : public Block { public: diff --git a/include/game.hpp b/include/game.hpp index f6f5334..5ebe042 100644 --- a/include/game.hpp +++ b/include/game.hpp @@ -2,7 +2,7 @@ #define __PTF_GAME_HPP__ #include "level.hpp" -#include "editor.hpp" +#include "widget_timer.hpp" /** * La classe Game gère l'affichage et les objets @@ -25,7 +25,6 @@ private: sf::Time next_frame_time; std::vector pending_kill; - std::shared_ptr return_state; Mode mode; DeathCause death_cause; diff --git a/include/gravity_block.hpp b/include/gravity_block.hpp index 653d641..b9a79af 100644 --- a/include/gravity_block.hpp +++ b/include/gravity_block.hpp @@ -4,7 +4,9 @@ #include #include #include "block.hpp" -#include "game.hpp" + +class Game; +enum class GravityDirection; class GravityBlock : public Block { public: diff --git a/include/kill_block.hpp b/include/kill_block.hpp index f069ca7..a9f036f 100644 --- a/include/kill_block.hpp +++ b/include/kill_block.hpp @@ -4,7 +4,8 @@ #include #include #include "block.hpp" -#include "game.hpp" + +class Game; class KillBlock : public Block { public: diff --git a/include/level.hpp b/include/level.hpp index f443371..c0b50c9 100644 --- a/include/level.hpp +++ b/include/level.hpp @@ -6,8 +6,8 @@ #include "state.hpp" #include "object.hpp" #include "player.hpp" -#include "manager.hpp" -#include "resource_manager.hpp" + +class Manager; // liste des directions de la gravité enum class GravityDirection {NORTH, EAST, SOUTH, WEST}; diff --git a/include/manager.hpp b/include/manager.hpp index 6c16650..316a96d 100644 --- a/include/manager.hpp +++ b/include/manager.hpp @@ -2,10 +2,11 @@ #define __SKIZZLE_MANAGER_HPP__ #include "resource_manager.hpp" -#include "state.hpp" #include #include +class State; + /** * Gestionnaire principal de tous les états, vues et * ressources du jeu @@ -37,6 +38,11 @@ public: */ static const sf::Time FRAME_TIME; + /** + * Taille d'une case de la grille du jeu + */ + static const float GRID; + Manager(); /** diff --git a/include/menu.hpp b/include/menu.hpp index cbbe9a5..572194b 100644 --- a/include/menu.hpp +++ b/include/menu.hpp @@ -1,11 +1,12 @@ #ifndef __PTF_MENU_HPP__ #define __PTF_MENU_HPP__ -#include "manager.hpp" #include "state.hpp" #include #include +class Manager; + /** * La classe Menu charge le menu du jeu * et permet de choisir entre jouer, lire les règles diff --git a/include/object.hpp b/include/object.hpp index 75c8162..863501b 100644 --- a/include/object.hpp +++ b/include/object.hpp @@ -5,8 +5,6 @@ #include #include #include "collision.hpp" -#include "manager.hpp" -#include "resource_manager.hpp" class Level; class Game; @@ -53,16 +51,6 @@ protected: static void init(std::ifstream& file, Object::Ptr object); public: - /** - * Identifiants uniques des propriétés communes modifiables - */ - static const unsigned int PROP_MASS; - static const unsigned int PROP_CHARGE; - static const unsigned int PROP_RESTITUTION; - static const unsigned int PROP_STATIC_FRICTION; - static const unsigned int PROP_DYNAMIC_FRICTION; - static const unsigned int PROP_LAYER; - Object(); virtual ~Object(); diff --git a/include/rules.hpp b/include/rules.hpp index b451a22..a918903 100644 --- a/include/rules.hpp +++ b/include/rules.hpp @@ -1,9 +1,10 @@ #ifndef __PTF_RULES_HPP__ #define __PTF_RULES_HPP__ -#include "manager.hpp" #include "state.hpp" +class Manager; + /** * La classe Rules affiche les règles du jeu */ @@ -26,5 +27,4 @@ public: virtual void frame(); }; - #endif diff --git a/include/state.hpp b/include/state.hpp index acd5812..cd6ca03 100644 --- a/include/state.hpp +++ b/include/state.hpp @@ -4,7 +4,6 @@ #include class ResourceManager; -class Object; class Manager; /** diff --git a/include/switch_block.hpp b/include/switch_block.hpp index 15031e9..b76b20c 100644 --- a/include/switch_block.hpp +++ b/include/switch_block.hpp @@ -4,7 +4,8 @@ #include #include #include "block.hpp" -#include "game.hpp" + +class Game; class SwitchBlock : public Block { public: diff --git a/include/widget_button.hpp b/include/widget_button.hpp index 6eb0702..766be17 100644 --- a/include/widget_button.hpp +++ b/include/widget_button.hpp @@ -3,7 +3,8 @@ #include #include -#include "manager.hpp" + +class Manager; /** * Affiche un bouton pouvant être cliqué diff --git a/include/widget_timer.hpp b/include/widget_timer.hpp index 81c9011..6ea9600 100644 --- a/include/widget_timer.hpp +++ b/include/widget_timer.hpp @@ -4,7 +4,8 @@ #include #include #include "widget_button.hpp" -#include "manager.hpp" + +class Manager; /** * Affiche le compteur de temps pouvant (ou non) diff --git a/include/widget_toolbar.hpp b/include/widget_toolbar.hpp index 737b7b0..484022c 100644 --- a/include/widget_toolbar.hpp +++ b/include/widget_toolbar.hpp @@ -5,7 +5,8 @@ #include #include "object.hpp" #include "level.hpp" -#include "manager.hpp" + +class Manager; /** * Représente un objet plaçable depuis la barre d'outils diff --git a/src/block.cpp b/src/block.cpp index 24ce1b9..13acec6 100644 --- a/src/block.cpp +++ b/src/block.cpp @@ -2,17 +2,16 @@ #include "level.hpp" #include "game.hpp" #include "player.hpp" -#include "constants.hpp" -#include "resource_manager.hpp" +#include "manager.hpp" const unsigned int Block::TYPE_ID = 2; Block::Block() : Object() { aabb = sf::FloatRect( - -Constants::GRID / 2, - -Constants::GRID / 2, - Constants::GRID, - Constants::GRID + -Manager::GRID / 2, + -Manager::GRID / 2, + Manager::GRID, + Manager::GRID ); } @@ -90,7 +89,7 @@ sf::FloatRect Block::getAABB() const { } float Block::getRadius() const { - return Constants::GRID / 2; + return Manager::GRID / 2; } unsigned int Block::getTypeId() const { diff --git a/src/collision.cpp b/src/collision.cpp index ba29403..ac6f8ec 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -8,176 +8,182 @@ #include /** - * Détermination des informations sur une collision entre - * un cercle et un rectangle + * Définition des variables et fonctions globales internes + * (accessibles uniquement dans ce fichier) */ -bool circleToAABB(CollisionData& data) { - Object::Ptr circle = data.obj_a; - Object::Ptr aabb = data.obj_b; +namespace { + /** + * Détermination des informations sur une collision entre + * un cercle et un rectangle + */ + bool circleToAABB(CollisionData& data) { + Object::Ptr circle = data.obj_a; + Object::Ptr aabb = data.obj_b; - // recherche du point le plus proche du centre du cercle - // sur le rectangle. On regarde la position relative du cercle - // par rapport au rectangle - sf::FloatRect box = aabb->getAABB(); - sf::Vector2f relpos = aabb->getPosition() - circle->getPosition(); - sf::Vector2f closest = relpos; + // recherche du point le plus proche du centre du cercle + // sur le rectangle. On regarde la position relative du cercle + // par rapport au rectangle + sf::FloatRect box = aabb->getAABB(); + sf::Vector2f relpos = aabb->getPosition() - circle->getPosition(); + sf::Vector2f closest = relpos; - // on restreint la position relative pour rester - // à l'intérieur du rectangle - if (closest.x < -box.width / 2) { - closest.x = -box.width / 2; - } + // on restreint la position relative pour rester + // à l'intérieur du rectangle + if (closest.x < -box.width / 2) { + closest.x = -box.width / 2; + } - if (closest.x > box.width / 2) { - closest.x = box.width / 2; - } + if (closest.x > box.width / 2) { + closest.x = box.width / 2; + } - if (closest.y < -box.height / 2) { - closest.y = -box.height / 2; - } + if (closest.y < -box.height / 2) { + closest.y = -box.height / 2; + } - if (closest.y > box.height / 2) { - closest.y = box.height / 2; - } + if (closest.y > box.height / 2) { + closest.y = box.height / 2; + } - // si la position n'a pas été changée, elle était déjà - // à l'intérieur du cercle : le cercle est dans le rectangle - float is_inside = false; + // si la position n'a pas été changée, elle était déjà + // à l'intérieur du cercle : le cercle est dans le rectangle + float is_inside = false; - if (relpos == closest) { - is_inside = true; + if (relpos == closest) { + is_inside = true; - // on se colle au bord le plus proche du rectangle - if (std::abs(relpos.x) > std::abs(relpos.y)) { - if (closest.x > 0) { - closest.x = box.width / 2; + // on se colle au bord le plus proche du rectangle + if (std::abs(relpos.x) > std::abs(relpos.y)) { + if (closest.x > 0) { + closest.x = box.width / 2; + } else { + closest.x = -box.width / 2; + } } else { - closest.x = -box.width / 2; - } - } else { - if (closest.y > 0) { - closest.y = box.height / 2; - } else { - closest.y = -box.height / 2; + if (closest.y > 0) { + closest.y = box.height / 2; + } else { + closest.y = -box.height / 2; + } } } - } - // la normale est portée par la direction - // du point le plus proche au centre du cercle - sf::Vector2f prenormal = relpos - closest; - float squared_length = prenormal.x * prenormal.x + prenormal.y * prenormal.y; + // la normale est portée par la direction + // du point le plus proche au centre du cercle + sf::Vector2f prenormal = relpos - closest; + float squared_length = prenormal.x * prenormal.x + prenormal.y * prenormal.y; - // si le cercle est à l'extérieur et que la normale est plus - // longue que son rayon, il n'y a pas collision - if (!is_inside && squared_length >= circle->getRadius() * circle->getRadius()) { - return false; - } + // si le cercle est à l'extérieur et que la normale est plus + // longue que son rayon, il n'y a pas collision + if (!is_inside && squared_length >= circle->getRadius() * circle->getRadius()) { + return false; + } - float length = std::sqrt(squared_length); - data.depth = circle->getRadius() - length; + float length = std::sqrt(squared_length); + data.depth = circle->getRadius() - length; - if (length != 0) { - data.normal = prenormal / length; - } + if (length != 0) { + data.normal = prenormal / length; + } - if (is_inside) { - data.normal *= -1.f; - } + if (is_inside) { + data.normal *= -1.f; + } - return true; -} - -/** - * Détermination des informations sur une collision entre - * un rectangle et un cercle - */ -bool AABBToCircle(CollisionData& data) { - // la collision rectangle -> cercle est la collision cercle -> rectangle - Object::Ptr transfer = data.obj_b; - data.obj_b = data.obj_a; - data.obj_a = transfer; - - return circleToAABB(data); -} - -/** - * Détermination des informations sur une collision entre - * deux cercles - */ -bool circleToCircle(CollisionData& data) { - Object::Ptr circle_a = data.obj_a; - Object::Ptr circle_b = data.obj_b; - - sf::Vector2f dir = circle_b->getPosition() - circle_a->getPosition(); - float squared_length = dir.x * dir.x + dir.y * dir.y; - float total_radius = circle_b->getRadius() + circle_a->getRadius(); - - // si les deux cercles sont à une distance supérieure - // à la somme de leurs deux rayons, il n'y a pas eu collision - if (squared_length > total_radius * total_radius) { - return false; - } - - float length = std::sqrt(squared_length); - - // les cercles sont sur la même position. - // Renvoie une normale apte à séparer les deux cercles - if (length == 0) { - data.depth = total_radius; - data.normal.x = 0; - data.normal.y = -1; return true; } - // il y a eu collision - data.depth = total_radius - length; - data.normal = dir / length; - return true; -} + /** + * Détermination des informations sur une collision entre + * un rectangle et un cercle + */ + bool AABBToCircle(CollisionData& data) { + // la collision rectangle -> cercle est la collision cercle -> rectangle + Object::Ptr transfer = data.obj_b; + data.obj_b = data.obj_a; + data.obj_a = transfer; -/** - * Détermination des informations sur une collision entre - * deux rectangles - */ -bool AABBToAABB(CollisionData& data) { - Object::Ptr aabb_a = data.obj_a; - Object::Ptr aabb_b = data.obj_b; - - sf::FloatRect box_a = aabb_a->getAABB(); - sf::FloatRect box_b = aabb_b->getAABB(); - sf::Vector2f relpos = aabb_b->getPosition() - aabb_a->getPosition(); - - float overlap_x = box_a.width / 2 + box_b.width / 2 - std::abs(relpos.x); - float overlap_y = box_a.height / 2 + box_b.height / 2 - std::abs(relpos.y); - - // si il n'y a pas de chauvauchement sur l'axe X et Y, pas de collision - if (overlap_x <= 0 || overlap_y <= 0) { - return false; + return circleToAABB(data); } - // on choisit l'axe de pénétration maximale pour calculer la normale - if (overlap_x < overlap_y) { - if (relpos.x < 0) { - data.normal.x = -1; - } else { - data.normal.x = 1; + /** + * Détermination des informations sur une collision entre + * deux cercles + */ + bool circleToCircle(CollisionData& data) { + Object::Ptr circle_a = data.obj_a; + Object::Ptr circle_b = data.obj_b; + + sf::Vector2f dir = circle_b->getPosition() - circle_a->getPosition(); + float squared_length = dir.x * dir.x + dir.y * dir.y; + float total_radius = circle_b->getRadius() + circle_a->getRadius(); + + // si les deux cercles sont à une distance supérieure + // à la somme de leurs deux rayons, il n'y a pas eu collision + if (squared_length > total_radius * total_radius) { + return false; } - data.normal.y = 0; - data.depth = overlap_x; - } else { - if (relpos.y < 0) { + float length = std::sqrt(squared_length); + + // les cercles sont sur la même position. + // Renvoie une normale apte à séparer les deux cercles + if (length == 0) { + data.depth = total_radius; + data.normal.x = 0; data.normal.y = -1; - } else { - data.normal.y = 1; + return true; } - data.normal.x = 0; - data.depth = overlap_y; + // il y a eu collision + data.depth = total_radius - length; + data.normal = dir / length; + return true; } - return true; + /** + * Détermination des informations sur une collision entre + * deux rectangles + */ + bool AABBToAABB(CollisionData& data) { + Object::Ptr aabb_a = data.obj_a; + Object::Ptr aabb_b = data.obj_b; + + sf::FloatRect box_a = aabb_a->getAABB(); + sf::FloatRect box_b = aabb_b->getAABB(); + sf::Vector2f relpos = aabb_b->getPosition() - aabb_a->getPosition(); + + float overlap_x = box_a.width / 2 + box_b.width / 2 - std::abs(relpos.x); + float overlap_y = box_a.height / 2 + box_b.height / 2 - std::abs(relpos.y); + + // si il n'y a pas de chauvauchement sur l'axe X et Y, pas de collision + if (overlap_x <= 0 || overlap_y <= 0) { + return false; + } + + // on choisit l'axe de pénétration maximale pour calculer la normale + if (overlap_x < overlap_y) { + if (relpos.x < 0) { + data.normal.x = -1; + } else { + data.normal.x = 1; + } + + data.normal.y = 0; + data.depth = overlap_x; + } else { + if (relpos.y < 0) { + data.normal.y = -1; + } else { + data.normal.y = 1; + } + + data.normal.x = 0; + data.depth = overlap_y; + } + + return true; + } } CollisionData::CollisionData() {} diff --git a/src/editor.cpp b/src/editor.cpp index a9ad35c..17b56ca 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1,28 +1,33 @@ +#include "manager.hpp" #include "editor.hpp" #include "game.hpp" -#include "block.hpp" -#include "constants.hpp" #include #include -const sf::Color SELECT_RECT_COLOR = sf::Color(33, 33, 33, 40); -const sf::Color SELECT_RECT_BORDER_COLOR = sf::Color(33, 33, 33, 127); -const sf::Color ZONE_POINT_COLOR = sf::Color(140, 15, 15, 255); -const sf::Color ZONE_BORDER_COLOR = sf::Color(200, 15, 15, 255); +/** + * Définition des variables et fonctions globales internes + * (accessibles uniquement dans ce fichier) + */ +namespace { + const sf::Color SELECT_RECT_COLOR = sf::Color(33, 33, 33, 40); + const sf::Color SELECT_RECT_BORDER_COLOR = sf::Color(33, 33, 33, 127); + const sf::Color ZONE_POINT_COLOR = sf::Color(140, 15, 15, 255); + const sf::Color ZONE_BORDER_COLOR = sf::Color(200, 15, 15, 255); -const float WHEEL_SCROLL_SPEED = -7.f; -const float POINTER_SCROLL_SPEED = 5.f; -const int POINTER_SCROLL_PADDING = 10; + const float WHEEL_SCROLL_SPEED = -7.f; + const float POINTER_SCROLL_SPEED = 5.f; + const int POINTER_SCROLL_PADDING = 10; +} /** * Arrondit le vecteur donné à une position * sur la grille */ inline sf::Vector2f roundVectorToGrid(sf::Vector2f input) { - input /= Constants::GRID; + input /= Manager::GRID; input.x = round(input.x); input.y = round(input.y); - input *= Constants::GRID; + input *= Manager::GRID; return input; } diff --git a/src/finish_block.cpp b/src/finish_block.cpp index 6d15fc9..f9c5dcd 100644 --- a/src/finish_block.cpp +++ b/src/finish_block.cpp @@ -1,3 +1,4 @@ +#include "resource_manager.hpp" #include "finish_block.hpp" #include "game.hpp" diff --git a/src/game.cpp b/src/game.cpp index b9353d0..e5161c5 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,8 +1,8 @@ #include #include +#include "manager.hpp" #include "game.hpp" #include "player.hpp" -#include "constants.hpp" Game::Game(Manager& manager) : Level(manager), widget_timer(manager, false), diff --git a/src/gravity_block.cpp b/src/gravity_block.cpp index a7a994c..585343e 100644 --- a/src/gravity_block.cpp +++ b/src/gravity_block.cpp @@ -1,3 +1,4 @@ +#include "resource_manager.hpp" #include "gravity_block.hpp" #include "game.hpp" diff --git a/src/kill_block.cpp b/src/kill_block.cpp index ede9df6..80409d9 100644 --- a/src/kill_block.cpp +++ b/src/kill_block.cpp @@ -1,3 +1,4 @@ +#include "resource_manager.hpp" #include "kill_block.hpp" #include "game.hpp" #include "player.hpp" diff --git a/src/level.cpp b/src/level.cpp index d87d7a1..d86be68 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -1,4 +1,4 @@ -#include "constants.hpp" +#include "manager.hpp" #include "level.hpp" #include "player.hpp" #include "block.hpp" @@ -14,134 +14,140 @@ #include /** - * Constante de gravité + * Définition des variables et fonctions globales internes + * (accessibles uniquement dans ce fichier) */ -const float GRAVITY = 235; +namespace { + /** + * Constante de gravité + */ + const float GRAVITY = 235; -/** - * Constante de déplacement des objets à déplacement manuel - */ -const float MOVE = 200; + /** + * Constante de déplacement des objets à déplacement manuel + */ + const float MOVE = 200; -/** - * Numéro actuel de version du format de fichier - */ -const unsigned int VERSION_NUMBER = 0; + /** + * 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 - * construction d'autres objets de ces types - */ -std::map> object_type_map = { - {Player::TYPE_ID, Player::load}, - {Block::TYPE_ID, Block::load}, - {GravityBlock::TYPE_ID, GravityBlock::load}, - {FinishBlock::TYPE_ID, FinishBlock::load}, - {KillBlock::TYPE_ID, KillBlock::load}, - {SwitchBlock::TYPE_ID, SwitchBlock::load} -}; + /** + * Dictionnaire associant les types d'objets + * à des instances qui seront utilisées pour la + * construction d'autres objets de ces types + */ + std::map> object_type_map = { + {Player::TYPE_ID, Player::load}, + {Block::TYPE_ID, Block::load}, + {GravityBlock::TYPE_ID, GravityBlock::load}, + {FinishBlock::TYPE_ID, FinishBlock::load}, + {KillBlock::TYPE_ID, KillBlock::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& zone, - std::string& background, std::string& music, - std::function object_callback = {} -) { - // ouverture du fichier - std::ifstream file; - file.open(path, std::ios::binary | std::ios::in); + /** + * 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& zone, + std::string& background, std::string& music, + std::function 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(&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(&pos_x), 4); - file.read(reinterpret_cast(&pos_y), 4); - - pos_x *= Constants::GRID; - pos_y *= Constants::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(&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) { + // 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 + "\" " + - "(type d'objet " + std::to_string(object_type) + " inconnu)" + "(" + std::string(strerror(errno)) + ")" ); } - // lecture de l'objet - object_callback(object_type_map[object_type](file)); + // 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(&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(&pos_x), 4); + file.read(reinterpret_cast(&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(&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)); + } } } @@ -228,8 +234,8 @@ void Level::save(std::string path) { file.write(&control_points, 1); for (int i = 0; i < control_points; i++) { - float pos_x = zone[i].x / Constants::GRID; - float pos_y = zone[i].y / Constants::GRID; + float pos_x = zone[i].x / Manager::GRID; + float pos_y = zone[i].y / Manager::GRID; file.write(reinterpret_cast(&pos_x), 4); file.write(reinterpret_cast(&pos_y), 4); diff --git a/src/manager.cpp b/src/manager.cpp index acae3ea..9c32193 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1,7 +1,9 @@ +#include "state.hpp" #include "manager.hpp" const unsigned int Manager::FPS = 60; const sf::Time Manager::FRAME_TIME = sf::seconds(1.f / Manager::FPS); +const float Manager::GRID = 32; Manager::Manager() : title(sf::String(L"")) { // préchargement des textures @@ -45,7 +47,7 @@ void Manager::start() { states.top()->processEvent(event); } - + // s'il n'y a plus d'état, on quitte if (states.empty()) { return; diff --git a/src/menu.cpp b/src/menu.cpp index c9a04db..774bf36 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -1,11 +1,10 @@ +#include "manager.hpp" #include "menu.hpp" #include "rules.hpp" #include "editor.hpp" #include "game.hpp" #include -const float MAX_WIDTH_PROPORTION = 1.f / 3.f; - Menu::Menu(Manager& manager) : State(manager) { background.setTexture(getResourceManager().getTexture("bg_menu.tga")); loadMainMenu(); diff --git a/src/object.cpp b/src/object.cpp index d0c3c29..f4f006f 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -1,28 +1,60 @@ +#include "manager.hpp" #include "object.hpp" #include "game.hpp" -#include "constants.hpp" #include "collision.hpp" #include -const unsigned int Object::PROP_MASS = 1; -const float DEFAULT_MASS = 0.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; +/** + * Définition des variables et fonctions globales internes + * (accessibles uniquement dans ce fichier) + */ +namespace { + // identifiant de la propriété de masse et sa valeur par défaut + // (une masse de zéro représente une masse infinie) + const unsigned int PROP_MASS = 1; + const float DEFAULT_MASS = 0.f; + + // identifiant de la propriété de charge et sa valeur par défaut + const unsigned int PROP_CHARGE = 2; + const float DEFAULT_CHARGE = 0.f; + + // identifiant de la propriété de restitution et sa valeur par défaut + // (plus la restitution est forte, plus les objets rebondissent) + const unsigned int PROP_RESTITUTION = 3; + const float DEFAULT_RESTITUTION = 0.4f; + + // identifiant du coefficient de frottement statique et sa valeur par défaut + // (coefficient proportionnel à la qté d'énergie nécessaire pour mettre + // en mouvement l'objet) + const unsigned int PROP_STATIC_FRICTION = 4; + const float DEFAULT_STATIC_FRICTION = 0.4f; + + // identifiant du coefficient de frottement dynamique et sa valeur par défaut + // (coefficient proportionnel aux pertes d'énergie en mouvement) + const unsigned int PROP_DYNAMIC_FRICTION = 5; + const float DEFAULT_DYNAMIC_FRICTION = 0.2f; + + // identifiant de la propriété calque et sa valeur par défaut + // (les objets sur deux calques différents n'entrent pas en collision, + // et les objets sont dessinés par ordre de calque) + const unsigned int PROP_LAYER = 6; + const int DEFAULT_LAYER = 0; + + // coefficient d'attraction. Proportionnel à la quantité d'énergie + // fournie par un objet chargé + const float ATTRACTION = 500000; + + // coefficients de correction positionnelle permettant de réduire + // la visibilité des erreurs d'arrondi des flottants. Le pourcentage + // de correction indique la proportion de correction par rapport à la + // vitesse et le seuil indique le minimum de correction appliqué + const float CORRECTION_PERCENTAGE = .5f; + const float CORRECTION_SLOP = .02f; +} Object::Object() : acceleration(0, 0), velocity(0, 0), position(0, 0), selected(false), inv_mass(-1.f), - - // valeurs par défaut pour les propriétés - // de tous les objets du jeu mass(DEFAULT_MASS), charge(DEFAULT_CHARGE), restitution(DEFAULT_RESTITUTION), @@ -40,7 +72,7 @@ void Object::init(std::ifstream& file, Object::Ptr object) { file.read(reinterpret_cast(&pos_y), 4); object->setPosition(sf::Vector2f( - pos_x * Constants::GRID, pos_y * Constants::GRID + pos_x * Manager::GRID, pos_y * Manager::GRID )); // lecture des propriétés facultatives @@ -48,37 +80,37 @@ void Object::init(std::ifstream& file, Object::Ptr object) { while (file.read(&prop_type, 1)) { switch (prop_type) { - case Object::PROP_MASS: + case PROP_MASS: float mass; file.read(reinterpret_cast(&mass), 4); object->setMass(mass); break; - case Object::PROP_CHARGE: + case PROP_CHARGE: float charge; file.read(reinterpret_cast(&charge), 4); object->setCharge(charge); break; - case Object::PROP_RESTITUTION: + case PROP_RESTITUTION: float restitution; file.read(reinterpret_cast(&restitution), 4); object->setRestitution(restitution); break; - case Object::PROP_STATIC_FRICTION: + case PROP_STATIC_FRICTION: float static_friction; file.read(reinterpret_cast(&static_friction), 4); object->setStaticFriction(static_friction); break; - case Object::PROP_DYNAMIC_FRICTION: + case PROP_DYNAMIC_FRICTION: float dynamic_friction; file.read(reinterpret_cast(&dynamic_friction), 4); object->setDynamicFriction(dynamic_friction); break; - case Object::PROP_LAYER: + case PROP_LAYER: char layer; file.read(&layer, 1); object->setLayer((int) layer - 127); @@ -93,8 +125,8 @@ void Object::init(std::ifstream& file, Object::Ptr 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; + float pos_x = getPosition().x / Manager::GRID; + float pos_y = getPosition().y / Manager::GRID; file.write(reinterpret_cast(&pos_x), 4); file.write(reinterpret_cast(&pos_y), 4); @@ -103,37 +135,37 @@ void Object::save(std::ofstream& file) const { char prop_type; if (mass != DEFAULT_MASS) { - prop_type = Object::PROP_MASS; + prop_type = PROP_MASS; file.write(&prop_type, 1); file.write(reinterpret_cast(&mass), 4); } if (charge != DEFAULT_CHARGE) { - prop_type = Object::PROP_CHARGE; + prop_type = PROP_CHARGE; file.write(&prop_type, 1); file.write(reinterpret_cast(&charge), 4); } if (restitution != DEFAULT_RESTITUTION) { - prop_type = Object::PROP_RESTITUTION; + prop_type = PROP_RESTITUTION; file.write(&prop_type, 1); file.write(reinterpret_cast(&restitution), 4); } if (static_friction != DEFAULT_STATIC_FRICTION) { - prop_type = Object::PROP_STATIC_FRICTION; + prop_type = PROP_STATIC_FRICTION; file.write(&prop_type, 1); file.write(reinterpret_cast(&static_friction), 4); } if (dynamic_friction != DEFAULT_DYNAMIC_FRICTION) { - prop_type = Object::PROP_DYNAMIC_FRICTION; + prop_type = PROP_DYNAMIC_FRICTION; file.write(&prop_type, 1); file.write(reinterpret_cast(&dynamic_friction), 4); } if (layer != DEFAULT_LAYER) { - prop_type = Object::PROP_LAYER; + prop_type = PROP_LAYER; file.write(&prop_type, 1); char write_layer = layer + 127; @@ -176,7 +208,7 @@ sf::Vector2f Object::getForces(const Game& game) const { // normalisation du vecteur direction qui porte // la force d'attraction, puis application de la norme attraction /= std::sqrt(distance_squared); - attraction *= Constants::ATTRACTION * ( + attraction *= ATTRACTION * ( (getCharge() * attractive->getCharge()) / distance_squared ); @@ -294,9 +326,8 @@ void Object::solveCollision(Game& game, Object::Ptr obj, const sf::Vector2f& nor } void Object::positionalCorrection(Object::Ptr obj, const sf::Vector2f& normal, float depth) { - float position_correction = std::max(depth - Constants::CORRECTION_SLOP, 0.0f) / - (getMassInvert() + obj->getMassInvert()) * - Constants::CORRECTION_PERCENTAGE; + float position_correction = std::max(depth - CORRECTION_SLOP, 0.0f) / + (getMassInvert() + obj->getMassInvert()) * CORRECTION_PERCENTAGE; setPosition(getPosition() - getMassInvert() * position_correction * normal); obj->setPosition(obj->getPosition() + obj->getMassInvert() * position_correction * normal); diff --git a/src/player.cpp b/src/player.cpp index 8cc83cb..11ecbd8 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -1,10 +1,6 @@ +#include "manager.hpp" #include "player.hpp" #include "game.hpp" -#include "game.hpp" -#include "block.hpp" -#include "constants.hpp" -#include -#include const unsigned int Player::TYPE_ID = 1; diff --git a/src/resource_manager.cpp b/src/resource_manager.cpp index f8c59e7..f1d935d 100644 --- a/src/resource_manager.cpp +++ b/src/resource_manager.cpp @@ -2,9 +2,6 @@ #include #include -using dir_iter = boost::filesystem::directory_iterator; -using fs_path = boost::filesystem::path; - ResourceManager::ResourceManager() : preloaded(false), music_volume(20), playing_state(false), current_music("") { // initialisation de la musique en bouclage et au volume par défaut @@ -17,8 +14,8 @@ void ResourceManager::preload() { return; } - fs_path current = boost::filesystem::current_path(); - dir_iter end; + boost::filesystem::path current = boost::filesystem::current_path(); + boost::filesystem::directory_iterator end; // on garde une référence aux chemins des différentes ressources textures_path = current / "res/textures"; @@ -27,7 +24,7 @@ void ResourceManager::preload() { musics_path = current / "res/musics"; // préchargement de toutes les textures - for (dir_iter it(textures_path); it != end; ++it) { + for (boost::filesystem::directory_iterator it(textures_path); it != end; ++it) { if (boost::filesystem::is_regular_file(it->path())) { std::string full_path = boost::filesystem::canonical(it->path()).string(); std::string name = it->path().filename().string(); @@ -47,7 +44,7 @@ void ResourceManager::preload() { } // préchargement de toutes les polices - for (dir_iter it(fonts_path); it != end; ++it) { + for (boost::filesystem::directory_iterator it(fonts_path); it != end; ++it) { if (boost::filesystem::is_regular_file(it->path())) { std::string full_path = boost::filesystem::canonical(it->path()).string(); std::string name = it->path().filename().string(); diff --git a/src/rules.cpp b/src/rules.cpp index db0e1e7..795dd0e 100644 --- a/src/rules.cpp +++ b/src/rules.cpp @@ -1,5 +1,5 @@ #include "rules.hpp" -#include +#include "manager.hpp" Rules::Rules(Manager& manager) : State(manager) { background.setTexture(getResourceManager().getTexture("bg_rules.png")); diff --git a/src/switch_block.cpp b/src/switch_block.cpp index b2e3441..bd671be 100644 --- a/src/switch_block.cpp +++ b/src/switch_block.cpp @@ -1,3 +1,4 @@ +#include "manager.hpp" #include "switch_block.hpp" #include "game.hpp" diff --git a/src/widget_button.cpp b/src/widget_button.cpp index 2f93266..1d7174d 100644 --- a/src/widget_button.cpp +++ b/src/widget_button.cpp @@ -1,12 +1,19 @@ +#include "manager.hpp" #include "widget_button.hpp" const unsigned int WidgetButton::ARROW_UP = 0; const unsigned int WidgetButton::ARROW_DOWN = 1; -const sf::Color ARROW_COLOR = sf::Color(33, 33, 33); -const sf::Color NORMAL_COLOR = sf::Color(230, 230, 230); -const sf::Color HOVER_COLOR = sf::Color(220, 220, 220); -const sf::Color ACTIVE_COLOR = sf::Color(190, 190, 190); +/** + * Définition des variables et fonctions globales internes + * (accessibles uniquement dans ce fichier) + */ +namespace { + const sf::Color ARROW_COLOR = sf::Color(33, 33, 33); + const sf::Color NORMAL_COLOR = sf::Color(230, 230, 230); + const sf::Color HOVER_COLOR = sf::Color(220, 220, 220); + const sf::Color ACTIVE_COLOR = sf::Color(190, 190, 190); +} WidgetButton::WidgetButton( Manager& manager, std::function click_cb, diff --git a/src/widget_timer.cpp b/src/widget_timer.cpp index 13730c7..b8f7643 100644 --- a/src/widget_timer.cpp +++ b/src/widget_timer.cpp @@ -1,5 +1,5 @@ +#include "manager.hpp" #include "widget_timer.hpp" -#include WidgetTimer::WidgetTimer(Manager& manager, bool can_change, std::function time_left_cb) : manager(manager), can_change(can_change), time_left_cb(time_left_cb), diff --git a/src/widget_toolbar.cpp b/src/widget_toolbar.cpp index b7e6b1f..f99c7c3 100644 --- a/src/widget_toolbar.cpp +++ b/src/widget_toolbar.cpp @@ -1,3 +1,4 @@ +#include "manager.hpp" #include "widget_toolbar.hpp" #include "block.hpp" #include "player.hpp" @@ -7,7 +8,14 @@ #include "kill_block.hpp" #include -const int PADDING = 8; + +/** + * Définition des variables et fonctions globales internes + * (accessibles uniquement dans ce fichier) + */ +namespace { + const int PADDING = 8; +} ToolbarCategory::Ptr WidgetToolbar::addCategory(sf::String name) { auto cat = ToolbarCategory::Ptr(new ToolbarCategory);