Ajout la possibilité d'interrompre la frame pour éviter segfault

This commit is contained in:
Mattéo Delabre 2016-04-08 00:19:01 +02:00
parent ddbd125f8f
commit c560073c5f
11 changed files with 186 additions and 91 deletions

View File

@ -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 é 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

View File

@ -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 é interrompu
*/
void frame();
virtual bool frame();
/**
* Mise en mode test : l'appui sur espace renvoie

View File

@ -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<std::pair<float, float>>& 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

View File

@ -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

View File

@ -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();

View File

@ -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 é interrompu
*/
virtual void frame() = 0;
virtual bool frame() = 0;
};
#endif

View File

@ -1,3 +1,4 @@
#include <iostream>
#include <cmath>
#include <algorithm>
#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<sf::Event>& 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<ObjectPtr>& 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> game = std::shared_ptr<Game>(new Game(manager));
clearSelection();
// copie des propriétés
game->setName(getName());

View File

@ -13,23 +13,15 @@ void Game::load(std::ifstream& file) {
manager.setTitle(getName());
}
void Game::frame() {
const std::vector<sf::Event>& 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() {

View File

@ -19,6 +19,7 @@ std::map<unsigned int, std::function<ObjectPtr(std::ifstream&)>> 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<sf::Event>& 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<ObjectPtr>& Level::getObjects() {
std::vector<std::pair<float, float>>& 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);
}

View File

@ -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<sf::Event>& 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;
}

View File

@ -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<sf::Event>& 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> game = std::shared_ptr<Game>(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<View> editor = std::shared_ptr<View>(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<NB_CHOICES; i++)
@ -147,5 +163,5 @@ void Menu::frame(){
window.draw(choice[i]);
}
window.display();
return false;
}