Gestion des evénements avec la SFML

Encapsulation dans une classe

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Salut,

La gestion des événements avec la SFML a toujours été problématique pour moi. Je n'ai jamais su réellement correctement implémenter une classe qui me permettait de créer et gérer les events facilement.

Cependant récemment j'ai fini par développer une solution qui, ma foi, me convient plutôt pas mal, mais, étant relativement débutant, je m’interroge sur son efficacité, sa propreté, et je me demande si ma façon de faire est bien ou non.

Donc, si quelque personne pouvait me donner leur avis, je leur en serais très reconnaissant !

Voici mon implémentation :

EventManager.hpp :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#ifndef H_EVENTMANAGER
#define H_EVENTMANAGER
 
#include <map>
#include <unordered_map>
#include <functional>
#include <iostream>
#include <SFML/Graphics.hpp>
 
namespace std
{
    template <>
    struct hash<sf::Rect<float> >
    {
        std::size_t operator()(const sf::Rect<float>& k) const
        {
            using std::size_t;
            using std::hash;
 
            return  ((hash<float>()(k.left)
                  ^ ((hash<float>()(k.top)    << 1)) >> 1)
                  ^ ((hash<float>()(k.width)  << 1)) >> 1)
                  ^  (hash<float>()(k.height) << 1);
 
        }
    };
 
 
}
 
 
 
class EventManager
{
public:
    EventManager();
 
    void processEvents(sf::RenderWindow *window);
 
    void linkEvent(sf::Event::EventType event, std::function<void(sf::Event)> f);
    void linkKey(sf::Keyboard::Key key, std::function<void()> f);
    void linkMouse(sf::Mouse::Button button, std::function<void()> f);
    void linkArea(sf::FloatRect rect, std::function<void()> f);
 
    void executeEvent(sf::Event::EventType e);
    void executeKey(sf::Keyboard::Key key);
    void executeArea(const sf::Window &parent);
 
    void clearEvents();
    void clearKeys();
    void clearArea();
 
 
private:
     std::map<sf::Event::EventType, std::function<void(sf::Event)> > m_eventMapping;
     std::map<sf::Keyboard::Key, std::function<void()> > m_keyMapping;
     std::map<sf::Mouse::Button, std::function<void()> > m_mouseMapping;
     std::unordered_map<sf::FloatRect, std::function<void()> > m_areaMapping;
 
};
 
 
 
 
 
#endif // H_EVENTMANAGER

EventManager.cpp :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
#include "EventManager.hpp"
 
EventManager::EventManager()
{
 
}
 
void EventManager::processEvents(sf::RenderWindow *window)
{
 
    sf::Event event;
    while (window->pollEvent(event))
    {
        // Checks if the event has been registered in the map
        if(m_eventMapping.count(event.type))
        {
            // If so, executes the function linked to it
            m_eventMapping[event.type](event);
        }
    }
 
    // Processes mouse button
    for(auto i : m_mouseMapping)
    {
        if(sf::Mouse::isButtonPressed(i.first))
        {
             m_mouseMapping[i.first]();
        }
    }
 
}
 
void EventManager::linkEvent(sf::Event::EventType event, std::function<void(sf::Event)> f)
{
    m_eventMapping[event] = f;
}
 
void EventManager::linkKey(sf::Keyboard::Key key, std::function<void()> f)
{
    m_keyMapping[key] = f;
}
 
void EventManager::linkMouse(sf::Mouse::Button button, std::function<void()> f)
{
    m_mouseMapping[button] = f;
}
 void EventManager::linkArea(sf::FloatRect rect, std::function<void()> f)
{
    m_areaMapping[rect] = f;
}
 
 
 
void EventManager::executeKey(sf::Keyboard::Key key)
{
    try
    {
        m_keyMapping[key]();
    }
    catch(...)
    {
        std::cout << "Exception occured in EventManager::executeKey !\n"
                  << "The key you pressed has probably not been linked to any function.\n";
    }
}
 
void EventManager::executeArea(const sf::Window &parent)
{
 
    sf::Vector2i pos = sf::Mouse::getPosition(parent);
 
    for(auto a : m_areaMapping)
    {
        if(pos.x >= a.first.left && pos.x < (a.first.left + a.first.width) && pos.y >= a.first.top && pos.y <= (a.first.top + a.first.height))
        {
            try
            {
                //m_areaMapping[a.first]();
                a.second();
            }
            catch(...)
            {
                std::cout << "Exception occured in EventManager::executeArea !\n"
                          << "The area you clicked in has probably not been linked to any valid function but has been registered.\n";
            }
        }
    }
}
 
void EventManager::clearEvents()
{
    m_eventMapping.clear();
}
 
void EventManager::clearKeys()
{
    m_keyMapping.clear();
}
 
void EventManager::clearArea()
{
    m_areaMapping.clear();
}

Extrait de mon main.cpp :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
int main()
{
    sf::VideoMode desktopMode= sf::VideoMode::getDesktopMode();
    MainWindow window(desktopMode, "The Journey Of The Moskiton"/*, sf::Style::Fullscreen*/);
    bool fullscreen = false;
 
    window.linkEvent(sf::Event::Closed,             [&window](sf::Event e){ window.close()               ; });
    window.linkEvent(sf::Event::KeyPressed,         [&window](sf::Event e){ window.executeKey(e.key.code); });
    window.linkEvent(sf::Event::MouseButtonPressed, [&window](sf::Event e){ window.executeArea(window)   ; });
 
    window.linkKey(sf::Keyboard::Escape, [&window](){ window.close(); });
    window.linkKey(sf::Keyboard::C,      [&window](){ window.clearRenderList(); window.clearArea(); });
    window.linkKey(sf::Keyboard::K,      [&window, &fullscreen, &desktopMode](){ fullscreen = !fullscreen ;
                                                                                 window.close();
                                                                                 if(fullscreen)
                                                                                 {
                                                                                    window.create(desktopMode, "The Journey Of The Moskiton", sf::Style::Fullscreen);
                                                                                 }
                                                                                 else
                                                                                 {
                                                                                    window.create(desktopMode, "The Journey Of The Moskiton");
                                                                                 }
                                                                                });
 
 
    Coord menuCoord; menuCoord.x = 20; menuCoord.y = 500;
    Coord menuTitleCoord; menuTitleCoord.x = 20; menuTitleCoord.y = 50;
    sf::Font titleFont;
    titleFont.loadFromFile("font/Pamela.ttf");
    Menu mainMenu;
    mainMenu.setFont("font/Pamela.ttf");
    mainMenu.setTitle("The Journey Of The Moskiton", 150, titleFont, menuTitleCoord);
    mainMenu.setPosition(menuCoord);
    mainMenu.addItem("Play");
    mainMenu.addItem("Editor");
    mainMenu.addItem("Options");
    mainMenu.addItem("Quit");
 
    Tileset tileset("tileset/tileset.png");
    Editor editor(tileset);
 
    window.linkArea(mainMenu.getItemBounds("Play"),    [](){std::cout << "Let's play\n"; });
    window.linkArea(mainMenu.getItemBounds("Editor"),  [&window, &editor](){std::cout << "Editor\n";
                                                                   window.clearRenderList(); window.clearArea();
                                                                   editor.open(window);
                                                                   });
    window.linkArea(mainMenu.getItemBounds("Options"), [](){std::cout << "Options\n";    });
    window.linkArea(mainMenu.getItemBounds("Quit"), [&window](){window.close();});
 
 
    sf::Texture bgTexture; bgTexture.loadFromFile("img/bg.jpg");
    sf::Sprite bgSpr(bgTexture);
    window.addToRender(&bgSpr);
 
    window.addToRender(&mainMenu);
    //sf::Texture tst = tileset.getTilesetTexture();
    //sf::Sprite t(tileset.getTilesetTexture());
    //sf::Sprite t = tileset.getTileSprite(5, 5);
    //window.addToRender(&t);
 
 
    while (window.isOpen())
    {
        window.processEvents();
        window.render();
    }
 
    return 0;
}

(La classe MainWindow hérite de EventManager)

Voilà, qu'en pensez-vous ?

Merci

Édité par Tycoon

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte