From c560073c5f93668d517108776cf0d5de60754ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre?= Date: Fri, 8 Apr 2016 00:19:01 +0200 Subject: [PATCH] =?UTF-8?q?Ajout=20la=20possibilit=C3=A9=20d'interrompre?= =?UTF-8?q?=20la=20frame=20pour=20=C3=A9viter=20segfault?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/editor.hpp | 33 ++++++++++++------- include/game.hpp | 12 +++++-- include/level.hpp | 22 +++++++++++++ include/manager.hpp | 4 +-- include/menu.hpp | 6 ++-- include/view.hpp | 6 ++-- src/editor.cpp | 80 +++++++++++++++++++++++++-------------------- src/game.cpp | 38 ++++++++++++--------- src/level.cpp | 29 ++++++++++++++++ src/manager.cpp | 11 ++----- src/menu.cpp | 36 ++++++++++++++------ 11 files changed, 186 insertions(+), 91 deletions(-) diff --git a/include/editor.hpp b/include/editor.hpp index cd9689f..d4052c0 100644 --- a/include/editor.hpp +++ b/include/editor.hpp @@ -49,16 +49,21 @@ private: void select(sf::Vector2f position, SelectionMode mode); void select(sf::Vector2f top_left, sf::Vector2f bottom_right); + /** + * Vide la sélection + */ + void clearSelection(); + + /** + * Sélectionne tout + */ + void selectAll(); + /** * Lance le test du niveau */ void test(); - /** - * Traite l'événement et renvoie true si on s'en est servi - */ - bool processEvent(const sf::Event& event); - protected: /** * Dessine tous les objets, le fond et @@ -66,20 +71,26 @@ protected: */ virtual void draw(); + /** + * Traite un événement et renvoie true si le + * dessin de la frame doit être interrompu + */ + virtual bool processEvent(const sf::Event& event); + public: Editor(Manager& manager); virtual ~Editor(); + /** + * Demande le passage à la frame suivante sur cette vue, + * renvoie true si le rendu de la frame a été interrompu + */ + virtual bool frame(); + /** * Charge un niveau de jeu depuis le fichier donné */ virtual void load(std::ifstream& file); - - /** - * Demande le passage à la frame suivante sur - * cette vue - */ - void frame(); }; #endif diff --git a/include/game.hpp b/include/game.hpp index e242a18..675dc35 100644 --- a/include/game.hpp +++ b/include/game.hpp @@ -28,6 +28,12 @@ protected: */ virtual void draw(); + /** + * Traite un événement et renvoie true si le + * dessin de la frame doit être interrompu + */ + virtual bool processEvent(const sf::Event& event); + public: Game(Manager& manager); virtual ~Game(); @@ -38,10 +44,10 @@ public: virtual void load(std::ifstream& file); /** - * Demande le passage à la frame suivante sur - * cette vue + * Demande le passage à la frame suivante sur cette vue, + * renvoie true si le rendu de la frame a été interrompu */ - void frame(); + virtual bool frame(); /** * Mise en mode test : l'appui sur espace renvoie diff --git a/include/level.hpp b/include/level.hpp index c6b3bc6..afc6e55 100644 --- a/include/level.hpp +++ b/include/level.hpp @@ -28,6 +28,12 @@ protected: */ virtual void draw(); + /** + * Traite un événement et renvoie true si le + * dessin de la frame doit être interrompu + */ + virtual bool processEvent(const sf::Event& event) = 0; + public: Level(Manager& manager); virtual ~Level(); @@ -42,6 +48,12 @@ public: */ virtual void save(); + /** + * Demande le passage à la frame suivante sur + * cette vue + */ + virtual bool frame(); + /** * Récupère le nom du niveau */ @@ -81,6 +93,16 @@ public: * Récupère la zone du niveau */ std::vector>& getZone(); + + /** + * Récupère le centre de la vue + */ + sf::Vector2f getViewCenter(); + + /** + * Modifie le centre de la vue + */ + void setViewCenter(sf::Vector2f set_view_center); }; #endif diff --git a/include/manager.hpp b/include/manager.hpp index fa7f6ed..9651610 100644 --- a/include/manager.hpp +++ b/include/manager.hpp @@ -63,12 +63,12 @@ public: /** * Renvoie la vue de la fenêtre (position centrale, taille) */ - sf::View getWindowView(); + sf::View& getWindowView(); /** * Modifie la vue de la fenêtre */ - void setWindowView(sf::View set_window_view); + void setWindowView(sf::View& set_window_view); /** * Renvoie le titre actuel de la fenêtre diff --git a/include/menu.hpp b/include/menu.hpp index 95baeac..6b9c463 100644 --- a/include/menu.hpp +++ b/include/menu.hpp @@ -25,11 +25,11 @@ public: /** * Dessine le menu - */ - void frame(); + */ + bool frame(); /** - * Permet de changer le choix sélectionné + * Permet de changer le choix sélectionné */ void MoveUp(); void MoveDown(); diff --git a/include/view.hpp b/include/view.hpp index ba2fd6c..b8e1445 100644 --- a/include/view.hpp +++ b/include/view.hpp @@ -18,10 +18,10 @@ public: virtual ~View(); /** - * Demande le passage à la frame suivante sur - * cette vue + * Demande le passage à la frame suivante sur cette vue, + * renvoie true si le rendu de la frame a été interrompu */ - virtual void frame() = 0; + virtual bool frame() = 0; }; #endif diff --git a/src/editor.cpp b/src/editor.cpp index b099ac0..db36657 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "editor.hpp" @@ -18,23 +19,24 @@ void Editor::load(std::ifstream& file) { manager.setTitle(sf::String(L"Édition de ") + getName()); } -void Editor::frame() { - const std::vector& events = manager.getEvents(); - - // traitement des événements - for (unsigned int i = 0; i < events.size(); i++) { - processEvent(events[i]); +bool Editor::frame() { + // si le dessin de la frame a été interrompu par + // le traitement événementiel, on arrête + if (Level::frame()) { + return true; } // dessin de la frame draw(); sf::sleep(sf::seconds(1.f / 30)); + + return true; } bool Editor::processEvent(const sf::Event& event) { // traitement des événements du widget timer if (widget_timer.processEvent(event)) { - return true; + return false; } // lorsque l'on clique dans l'éditeur @@ -48,12 +50,10 @@ bool Editor::processEvent(const sf::Event& event) { drag_start = position; drag_end = position; drag_mode = DragMode::SELECT_RECT; - - return true; } // clic sur un objet : démarrage de la sélection libre - if (pointed_object != nullptr) { + else if (pointed_object != nullptr) { if (manager.isKeyPressed(sf::Keyboard::LControl)) { drag_start = position; drag_end = position; @@ -63,17 +63,16 @@ bool Editor::processEvent(const sf::Event& event) { } else { select(pointed_object, SelectionMode::FLIP); } - - return true; } // clic gauche dans le vide : démarrage du placement en drag&drop - drag_start = position; - drag_end = position; - drag_mode = DragMode::PLACE; + else { + drag_start = position; + drag_end = position; + drag_mode = DragMode::PLACE; - select(addObject(position), SelectionMode::REPLACE); - return true; + select(addObject(position), SelectionMode::REPLACE); + } } if (event.mouseButton.button == sf::Mouse::Right) { @@ -84,7 +83,6 @@ bool Editor::processEvent(const sf::Event& event) { drag_mode = DragMode::REMOVE; removeObject(pointed_object); - return true; } } } @@ -98,19 +96,16 @@ bool Editor::processEvent(const sf::Event& event) { // mode placement d'objets if (drag_mode == DragMode::PLACE && pointed_object == nullptr) { select(addObject(position), SelectionMode::ADD); - return true; } // mode suppression d'objets if (drag_mode == DragMode::REMOVE && pointed_object != nullptr) { removeObject(pointed_object); - return true; } // mode sélection libre : on l'objet à la sélection if (drag_mode == DragMode::SELECT_BULK) { select(position, SelectionMode::ADD); - return true; } } @@ -124,7 +119,6 @@ bool Editor::processEvent(const sf::Event& event) { } drag_mode = DragMode::NONE; - return true; } // gestion des touches @@ -139,13 +133,20 @@ bool Editor::processEvent(const sf::Event& event) { ), objects.end()); } - selection.clear(); - return true; + clearSelection(); + } + + // appui sur Ctrl + A : sélection de tous les objets + if (event.key.code == sf::Keyboard::A && event.key.control) { + selectAll(); } // appui sur espace : test du niveau en cours d'édition if (event.key.code == sf::Keyboard::Space) { test(); + + // demande l'interruption du dessin de la + // frame car l'objet risque d'être détruit return true; } } @@ -257,11 +258,7 @@ void Editor::select(ObjectPtr object, SelectionMode mode) { // pour REPLACE, on sélectionne forcément l'objet // pour FLIP, on le sélectionne s'il ne l'est pas, on le désélectionne sinon if (mode == SelectionMode::REPLACE || mode == SelectionMode::FLIP) { - for (unsigned int i = 0; i < selection.size(); i++) { - selection[i]->setSelected(false); - } - - selection.clear(); + clearSelection(); // on resélectionne l'objet ssi. on force la sélection // ou s'il n'était pas déjà sélectionné @@ -291,12 +288,7 @@ void Editor::select(sf::Vector2f top_left, sf::Vector2f bottom_right) { std::abs(bottom_right.y - top_left.y) ); - // réinitialisation de la sélectionne - for (unsigned int i = 0; i < selection.size(); i++) { - selection[i]->setSelected(false); - } - - selection.clear(); + clearSelection(); // sélection des éléments intersectant le rectangle for (unsigned int i = 0; i < objects.size(); i++) { @@ -306,8 +298,26 @@ void Editor::select(sf::Vector2f top_left, sf::Vector2f bottom_right) { } } +void Editor::clearSelection() { + for (unsigned int i = 0; i < selection.size(); i++) { + selection[i]->setSelected(false); + } + + selection.clear(); +} + +void Editor::selectAll() { + std::vector& objects = getObjects(); + + for (unsigned int i = 0; i < objects.size(); i++) { + objects[i]->setSelected(true); + selection.push_back(objects[i]); + } +} + void Editor::test() { std::shared_ptr game = std::shared_ptr(new Game(manager)); + clearSelection(); // copie des propriétés game->setName(getName()); diff --git a/src/game.cpp b/src/game.cpp index f4d821d..7428f5f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -13,23 +13,15 @@ void Game::load(std::ifstream& file) { manager.setTitle(getName()); } -void Game::frame() { - const std::vector& events = manager.getEvents(); - sf::Time current_time = manager.getCurrentTime(); - - // traitement des événements - for (unsigned int i = 0; i < events.size(); i++) { - const sf::Event& event = events[i]; - - // appui sur espace en mode test : retour à l'éditeur - if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space && test_mode) { - test_mode = false; - manager.setView(return_view); - return; // important : ne pas dessiner la frame - // on risque d'avoir perdu le pointeur en changeant de vue - } +bool Game::frame() { + // si le dessin de la frame a été interrompu par + // le traitement événementiel, on arrête + if (Level::frame()) { + return true; } + sf::Time current_time = manager.getCurrentTime(); + if (current_time >= next_frame_time) { // si nous sommes en retard ou dans les temps // on replanifie la prochaine frame @@ -47,6 +39,22 @@ void Game::frame() { // le temps nécessaire pour revenir dans les temps sf::sleep(next_frame_time - current_time); } + + return false; +} + +bool Game::processEvent(const sf::Event& event) { + // appui sur espace en mode test : retour à l'éditeur + if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space && test_mode) { + test_mode = false; + manager.setView(return_view); + + // demande l'interruption du dessin de la + // frame car l'objet risque d'être détruit + return true; + } + + return false; } void Game::draw() { diff --git a/src/level.cpp b/src/level.cpp index 392dca1..fc734e0 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -19,6 +19,7 @@ std::map> object_type_map Level::Level(Manager& manager) : View(manager), total_time(30) {} Level::~Level() { + setViewCenter(sf::Vector2f(0, 0)); objects.clear(); } @@ -28,6 +29,9 @@ void Level::load(std::ifstream& file) { objects.clear(); } + // positionnement de la vue au centre + setViewCenter(sf::Vector2f(0, 0)); + // lecture de la signture du fichier ("BAR") char signature[3]; file.read(signature, sizeof(signature)); @@ -111,6 +115,23 @@ void Level::save() { // TODO: faire une fonction d'enregistrement } +bool Level::frame() { + const std::vector& events = manager.getEvents(); + + // traitement des événements + for (unsigned int i = 0; i < events.size(); i++) { + if (processEvent(events[i])) { + // /!\ On arrête là si on a demandé l'interruption. + // Il est important de ne plus appeler aucune autre + // fonction de la classe pour éviter une erreur + // de segmentation + return true; + } + } + + return false; +} + void Level::draw() { // efface la scène précédente et dessine la couche de fond sf::RenderWindow& window = manager.getWindow(); @@ -166,3 +187,11 @@ std::vector& Level::getObjects() { std::vector>& Level::getZone() { return zone; } + +sf::Vector2f Level::getViewCenter() { + return manager.getWindowView().getCenter(); +} + +void Level::setViewCenter(sf::Vector2f set_view_center) { + manager.getWindowView().setCenter(set_view_center); +} diff --git a/src/manager.cpp b/src/manager.cpp index 65f02f0..ee57158 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -18,13 +18,6 @@ void Manager::start() { return; } - // lorsque la fenêtre est redimensionnée par l'utilisateur - if (event.type == sf::Event::Resized) { - // mise à jour de la caméra en fonction de la taille de la fenêtre - sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); - setWindowView(sf::View(visibleArea)); - } - events.push_back(event); } @@ -63,11 +56,11 @@ const std::vector& Manager::getEvents() { return events; } -sf::View Manager::getWindowView() { +sf::View& Manager::getWindowView() { return window_view; } -void Manager::setWindowView(sf::View set_window_view) { +void Manager::setWindowView(sf::View& set_window_view) { window.setView(set_window_view); window_view = set_window_view; } diff --git a/src/menu.cpp b/src/menu.cpp index 451aaf1..cea1ce5 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -4,7 +4,7 @@ Menu::Menu(Manager& manager) : View(manager){ manager.getResourceManager().setMusic("menu.wav"); manager.getResourceManager().playMusic(); - + menu1(); //mise en place des propriétés des textes affichés dans le menu choice[0].setFont(manager.getResourceManager().getFont("Raleway-Regular.ttf")); @@ -19,7 +19,7 @@ Menu::Menu(Manager& manager) : View(manager){ } //choix sélectionné à l'ouverture du menu - selection = 0; + selection = 0; } Menu::~Menu(){ @@ -47,7 +47,7 @@ void Menu::menu2(){ } void Menu::MoveUp() -{ +{ //change la couleur du choix sélectionné if(selection-1 >= 0) { @@ -68,15 +68,15 @@ void Menu::MoveDown() } } -void Menu::frame(){ +bool Menu::frame(){ sf::RenderWindow& window = manager.getWindow(); window.clear(sf::Color(66, 40, 245)); const std::vector& events = manager.getEvents(); - + for (unsigned int i = 0; i < events.size(); i++) { const sf::Event& event = events[i]; - + // gestion des touches if (event.type == sf::Event::KeyPressed) { if (event.key.code == sf::Keyboard::Up) { @@ -90,7 +90,7 @@ void Menu::frame(){ //si on se trouve dans le menu 2 permettant de choisir les niveaux if(menu_nb == 2){ - //si on choisit "tutoriel", on charge le niveau tutoriel et on + //si on choisit "tutoriel", on charge le niveau tutoriel et on //la vue passe à Game if(selection == 0){ std::shared_ptr game = std::shared_ptr(new Game(manager)); @@ -108,11 +108,19 @@ void Menu::frame(){ file.close(); manager.setView(game); + + // demande l'interruption du dessin de la + // frame car l'objet risque d'être détruit + return true; } //si on choisit "Quitter", la fenêtre se ferme if(selection == 3){ manager.getWindow().close(); + + // demande l'interruption du dessin de la + // frame car l'objet risque d'être détruit + return true; } } if(menu_nb == 1){ @@ -122,24 +130,32 @@ void Menu::frame(){ menu2(); } if(selection==1){ - + } //si on choisit "créer un niveau", la vue se met sur Editor if(selection==2){ std::shared_ptr editor = std::shared_ptr(new Editor(manager)); manager.setView(editor); + + // demande l'interruption du dessin de la + // frame car l'objet risque d'être détruit + return true; } //si on choisit "quitter", la fenêtre se ferme if(selection==3){ manager.getWindow().close(); + + // demande l'interruption du dessin de la + // frame car l'objet risque d'être détruit + return true; } } } } - + } for(int i=0; i