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
+0
-0