{"id":344,"date":"2015-02-24T12:01:31","date_gmt":"2015-02-24T12:01:31","guid":{"rendered":"http:\/\/anthroponaute.fr\/blog-informatique\/?p=344"},"modified":"2016-07-19T10:47:18","modified_gmt":"2016-07-19T10:47:18","slug":"classe-pour-gerer-les-evenements-du-jeu-event","status":"publish","type":"post","link":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/?p=344","title":{"rendered":"Syst\u00e8me d&rsquo;Events pour g\u00e9rer les \u00e9v\u00e9nements du jeu (1\u00e8re approche)"},"content":{"rendered":"<p><a href=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2015\/02\/b7ef9923828960d1a0935b08fb5ac0d2.jpg\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone  wp-image-5177\" src=\"https:\/\/anthropoya.cluster014.ovh.net\/blog-informatique\/wp-content\/uploads\/2015\/02\/b7ef9923828960d1a0935b08fb5ac0d2.jpg\" alt=\"b7ef9923828960d1a0935b08fb5ac0d2\" width=\"502\" height=\"378\" srcset=\"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/02\/b7ef9923828960d1a0935b08fb5ac0d2.jpg 1144w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/02\/b7ef9923828960d1a0935b08fb5ac0d2-300x226.jpg 300w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/02\/b7ef9923828960d1a0935b08fb5ac0d2-1024x772.jpg 1024w, https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/wp-content\/uploads\/2015\/02\/b7ef9923828960d1a0935b08fb5ac0d2-624x470.jpg 624w\" sizes=\"(max-width: 502px) 100vw, 502px\" \/><\/a><\/p>\n<p><strong>Intro :<\/strong><\/p>\n<p>Dans la conception d&rsquo;un jeu il est tr\u00e8s important d\u2019\u00e9num\u00e9rer tous les m\u00e9canismes intrins\u00e8ques au comportement du jeu, c&rsquo;est-\u00e0-dire des \u00e9v\u00e9nements du gameplay, du son, de l&rsquo;interface, du r\u00e9seau, de la gestion des collisions et de l&rsquo;IA.<\/p>\n<p>Ceci est une <strong>premi\u00e8re approche<\/strong> au probl\u00e8me.<\/p>\n<p>J&rsquo;ai \u00e9crit un article sur une deuxi\u00e8me approche plus juste et mieux adapt\u00e9e.<\/p>\n<p>Ici on parle des \u00e9v\u00e9nements, nomm\u00e9s aussi Events.<\/p>\n<p><strong>Pr\u00e9requis :<\/strong><\/p>\n<p>La compr\u00e9hension de l&rsquo;utilisation de la classe <em>DataParameters.<\/em><\/p>\n<p><strong>Explications \/ exemples :<\/strong><\/p>\n<p>On se sert de deux macros.<\/p>\n<p>Voici des macros permettant de simplifier la d\u00e9finition de vos Events\u00a0 :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\n#define DECLARE_GAME_EVENT(eventName) class eventName : public Event \\\r\n\u00a0\u00a0 \u00a0\u00a0 { \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 public: \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 eventName() :\u00a0 \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 Event(#eventName, 0) \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 {} \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 virtual bool performTask(); \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 static const int GameEventID = Event::eventName; \\\r\n\u00a0\u00a0 \u00a0\u00a0 };\r\n\r\n#define DECLARE_GAME_EVENT_WITH_PARAMETERS(eventName, argsNumber, ...) class eventName : public Event \\\r\n\u00a0\u00a0 \u00a0\u00a0 { \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 public: \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 eventName() :\u00a0 \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 Event(#eventName, argsNumber, __VA_ARGS__)\\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 {} \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 virtual bool performTask(); \\\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 static const int GameEventID = Event::eventName; \\\r\n\u00a0\u00a0 \u00a0\u00a0 };\r\n\r\n#define IMPLEMENT_GAME_EVENT(eventName) bool eventName::performTask()\r\n\r\n<\/pre>\n<p>Je vous fournis deux macros : une pour un Event sans param\u00e8tres et une autre pour les Events<br \/>\navec param\u00e8tres.<\/p>\n<p>Voici le fichier .h de la classe Event :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\nclass Event\r\n{\r\npublic:\r\n\u00a0\u00a0\u00a0 static const enum GameEvents\r\n\u00a0\u00a0\u00a0 {\r\n        \/* Exemples d'events \u00e0 titre indicatif *\/\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  OnTakeScreenShot,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnMobAggro,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnMobUnAggro,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnMobIdle,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnMobAttack,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnConsoleScrollUp,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnConsoleScrollDown,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnHeal,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnEnemyDamage,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnFocusTarget,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnSpellCast,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnMount,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnUnMount,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnGUIButtonClick,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnGUIButtonHover,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnAddItem,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnRemoveItem,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnKill,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnTextPaste,\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0OnToggleCameraMode\r\n\u00a0\u00a0\u00a0 };\r\n\r\n\u00a0\u00a0\u00a0 Event(const char* sName, unsigned int iArgsNumber, ...);\r\n\r\n\u00a0\u00a0\u00a0 virtual ~Event();\r\n\u00a0\u00a0\u00a0 virtual void trigger();\r\n\r\n\u00a0\u00a0\u00a0 const std::string&amp; getName() const;\r\n\u00a0\u00a0\u00a0 time_t getTimeLastTriggered() const;\r\n\u00a0\u00a0\u00a0 bool hasLastTriggerSucceed() const;\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Associe un autre event \u00e0 invoquer en cascade\r\n\u00a0\u00a0 \u00a0void pushChildEvent(Event* pEvent);\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Param\u00e8tre associ\u00e9 \u00e0 l'Event invoqu\u00e9\r\n\u00a0\u00a0 \u00a0void setParameter(DataParameters&amp; params);\r\n\u00a0\u00a0 \u00a0\/\/ Param\u00e8tre associ\u00e9 \u00e0 l'Event invoqu\u00e9\r\n\u00a0\u00a0 \u00a0DataParameters* getParameters();\r\n\r\n\u00a0\u00a0 \u00a0bool getLogWriting();\r\n\u00a0\u00a0 \u00a0void setLogWriting(bool bWrite);\r\n\r\n\u00a0\u00a0 \u00a0void getParametersName(std::vector&lt;std::string&gt;&amp; paramsNames);\r\n\r\nprotected:\r\n\u00a0\u00a0\u00a0 virtual bool performTask() = 0;\r\n\u00a0\u00a0\u00a0 void setName(const std::string&amp; sName);\r\n\r\nprivate:\r\n\u00a0\u00a0\u00a0 std::string m_sName;\r\n\u00a0\u00a0\u00a0 time_t m_timeLastTriggered;\r\n\u00a0\u00a0\u00a0 bool m_bLastTriggerSucceed;\r\n\r\n\u00a0\u00a0 \u00a0std::vector&lt;Event*&gt; m_childrenEvents;\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Une liste des noms de param\u00e8tres de l'event\r\n\u00a0\u00a0 \u00a0std::vector&lt;std::string&gt; m_parametersNames;\r\n\u00a0\u00a0 \u00a0DataParameters m_params;\r\n\r\n\u00a0\u00a0 \u00a0bool m_bLogWriting;\r\n};\r\n\r\n<\/pre>\n<p>Voici le fichier .cpp<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\nEvent::Event(const char* sName, unsigned int iArgsNumber, ...) :\r\nm_sName(sName),\r\nm_timeLastTriggered(0),\r\nm_bLastTriggerSucceed(false),\r\nm_bLogWriting(true)\r\n{\r\n\u00a0\u00a0\u00a0 va_list args;\r\n\u00a0\u00a0\u00a0 va_start(args, iArgsNumber);\r\n\u00a0\u00a0 \u00a0for (unsigned i = 0; i &lt; iArgsNumber; i++)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0std::string sArgName = va_arg(args, char*);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0m_parametersNames.push_back(sArgName);\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0\u00a0 va_end(args);\r\n}\r\n\r\nEvent::~Event()\r\n{\r\n}\r\n\r\nvoid Event::trigger()\r\n{\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 time(&amp;m_timeLastTriggered);\r\n\u00a0\u00a0\u00a0 m_bLastTriggerSucceed = performTask();\r\n\r\n\u00a0\u00a0 \u00a0if (getLogWriting())\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/SYSTEM_LOG-&gt;log(Logger::MessageType::MSG_TYPE_EVENT, std::string(&quot;Event effectu\u00e9 : &quot; + getName()).c_str());\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Invoque aussi les events enfants et associ\u00e9s (en cascade) :\r\n\u00a0\u00a0 \u00a0for (unsigned int i = 0; i &lt; m_childrenEvents.size(); i++)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Event* pEvent = m_childrenEvents[i];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (pEvent)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pEvent-&gt;trigger();\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\nconst std::string&amp; Event::getName() const\r\n{\r\n\u00a0\u00a0\u00a0 return m_sName;\r\n}\r\n\r\ntime_t Event::getTimeLastTriggered() const\r\n{\r\n\u00a0\u00a0\u00a0 return m_timeLastTriggered;\r\n}\r\n\r\nbool Event::hasLastTriggerSucceed() const\r\n{\r\n\u00a0\u00a0\u00a0 return m_bLastTriggerSucceed;\r\n}\r\n\r\nvoid Event::setName(const std::string&amp; sName)\r\n{\r\n\u00a0\u00a0\u00a0 m_sName = sName;\r\n}\r\n\r\nvoid Event::pushChildEvent(Event* pEvent)\r\n{\r\n\u00a0\u00a0 \u00a0if (pEvent)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0m_childrenEvents.push_back(pEvent);\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n\r\nvoid Event::setParameter(DataParameters&amp; params)\r\n{\r\n\u00a0\u00a0 \u00a0m_params = params;\r\n}\r\n\r\nDataParameters* Event::getParameters()\r\n{\r\n\u00a0\u00a0 \u00a0return &amp;m_params;\r\n}\r\n\r\nbool Event::getLogWriting()\r\n{\r\n\u00a0\u00a0 \u00a0return m_bLogWriting;\r\n}\r\n\r\nvoid Event::setLogWriting(bool bWrite)\r\n{\r\n\u00a0\u00a0 \u00a0m_bLogWriting = bWrite;\r\n}\r\n\r\nvoid Event::getParametersName(std::vector&lt;std::string&gt;&amp; paramsNames)\r\n{\r\n\u00a0\u00a0 \u00a0paramsNames = m_parametersNames;\r\n}\r\n<\/pre>\n<p>On d\u00e9finit les Events comme suit :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\nDECLARE_GAME_EVENT( OnTakeScreenShot );\r\nDECLARE_GAME_EVENT( OnMobAggro );\r\nDECLARE_GAME_EVENT( OnMobUnAggro );\r\nDECLARE_GAME_EVENT( OnMobIdle );\r\nDECLARE_GAME_EVENT( OnMobAttack );\r\nDECLARE_GAME_EVENT( OnConsoleScrollUp );\r\nDECLARE_GAME_EVENT( OnConsoleScrollDown );\r\nDECLARE_GAME_EVENT( OnHeal );\r\nDECLARE_GAME_EVENT( OnEnemyDamage );\r\nDECLARE_GAME_EVENT( OnFocusTarget );\r\nDECLARE_GAME_EVENT( OnSpellCast );\r\nDECLARE_GAME_EVENT( OnMount );\r\nDECLARE_GAME_EVENT( OnUnMount );\r\nDECLARE_GAME_EVENT( OnGUIButtonClick );\r\nDECLARE_GAME_EVENT( OnGUIButtonHover );\r\nDECLARE_GAME_EVENT( OnAddItem );\r\nDECLARE_GAME_EVENT( OnRemoveItem );\r\nDECLARE_GAME_EVENT( OnKill );\r\nDECLARE_GAME_EVENT( OnTextPaste );\r\nDECLARE_GAME_EVENT( OnToggleCameraMode );\r\n\r\n<\/pre>\n<p>Et on impl\u00e9mente les Events comme suit :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\nIMPLEMENT_GAME_EVENT( OnTextPaste )\r\n{\r\n\u00a0\u00a0 \u00a0if (OpenClipboard(NULL))\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0HANDLE hData = GetClipboardData(CF_TEXT);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (hData)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0char* pszText = static_cast&lt;char*&gt;(GlobalLock(hData));\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/ Release the lock\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0GlobalUnlock( hData );\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\/\/ Release the clipboard\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0CloseClipboard();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (strlen(pszText) &gt; 100)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return true;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0switch (GAME_STATE_MANAGER-&gt;getState())\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case GameState::ON_CONSOLE:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0CONSOLE-&gt;appendCommandLineText(pszText);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case GameState::ON_LOADING_MENU:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0return true;\r\n}\r\n\r\nIMPLEMENT_GAME_EVENT( OnCameraMovementUpwardRight\u00a0 )\r\n{\r\n\u00a0\u00a0 \u00a0switch (GAME_STATE_MANAGER-&gt;getState())\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0case GameState::ON_WORLD:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0getGlobalSystems()-&gt;\r\n                 getCameraManager()-&gt;setCameraMovement(CameraManager::CAMERA_MOVE_UPWARD |\r\n                                                       CameraManager::CAMERA_STRAFE_RIGHT);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0break;\r\n\u00a0\u00a0 \u00a0}\r\n\r\n\u00a0\u00a0 \u00a0return true;\r\n}\r\n\r\n<\/pre>\n<p>Voici le fichier EventManager.h :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\r\nclass Event;\r\nclass DataParameters;\r\n\r\nclass EventManager\r\n{\r\npublic:\r\n\u00a0\u00a0\u00a0 EventManager();\r\n\u00a0\u00a0\u00a0 virtual ~EventManager();\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 void registerEvent(Event* const pEvent);\r\n\r\n\u00a0\u00a0 \u00a0\/\/ Invoque un event avec sp\u00e9cification de param\u00e8tres\r\n\u00a0\u00a0 \u00a0void triggerEvent(const std::string&amp; sEventName);\r\n\u00a0\u00a0 \u00a0\/\/ Invoque un event\r\n\u00a0\u00a0 \u00a0void triggerEvent(const std::string&amp; sEventName, DataParameters&amp; p);\r\n\r\n\u00a0\u00a0 \u00a0\/\/ On invoque la fonction callback depuis un fichier script lua\r\n\u00a0\u00a0 \u00a0void triggerLuaCallback(const std::string&amp; sEventName, DataParameters&amp; p);\r\n\u00a0\u00a0 \u00a0void triggerLuaCallback(const std::string&amp; sEventName);\r\n\r\n\u00a0\u00a0 \u00a0\/\/ On peut parenter un event\r\n\r\n\u00a0\u00a0 \u00a0void attachEventTo(Event* pEventToAttach, Event* pChildEvent);\r\n\r\n\u00a0\u00a0 \u00a0Event* getEvent(const std::string&amp; sEventName);\r\n\r\n\u00a0\u00a0 \u00a0void setParametersToEvent(std::string sEventName, DataParameters pParam);\r\n\r\n\u00a0\u00a0 \u00a0void getEventsNames(std::vector&lt;std::string&gt;&amp; paramNames);\r\n\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\/\/ On peut invoquer des events sp\u00e9cicifiques \u00e0 travers une pile d'appel\r\n\u00a0\u00a0 \u00a0void pushEvent(const std::string&amp; sName);\r\n\u00a0\u00a0 \u00a0void triggerPushedEvents();\r\n\u00a0\u00a0 \u00a0void clearPushedEvent();\r\n\r\nprivate:\r\n\u00a0\u00a0 \u00a0\/\/ La liste des events\r\n\u00a0\u00a0\u00a0 std::map&lt;std::string, Event*&gt; m_events;\r\n\u00a0\u00a0\u00a0 std::map&lt;std::string, Event*&gt; m_pushedEvents;\r\n\r\n};\r\n\r\n<\/pre>\n<p>Voici le fichier EventManager.cpp<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nEventManager::EventManager()\r\n{\r\n}\r\n\r\nEventManager::~EventManager()\r\n{\r\n}\r\n\r\nvoid EventManager::registerEvent(Event* const pEvent)\r\n{\r\n\u00a0\u00a0 \u00a0SKIP_IF_FAILED_AssertMsg(pEvent != NULL, &quot;pEvent NULL&quot;)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0std::string sName = pEvent-&gt;getName();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0SKIP_IF_FAILED_AssertMsg(m_events.count(sName) == 0, &quot;Event d\u00e9j\u00e0 enregistr\u00e9&quot;)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0m_events[sName] = pEvent;\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n\r\n\/\/ On d\u00e9clenche sans param\u00e8tre\r\nvoid EventManager::triggerEvent(const std::string&amp; sEventName)\r\n{\r\n\u00a0\u00a0 \u00a0if (m_events.count(sEventName) &gt; 0)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Event* pEvent = m_events[sEventName];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pEvent-&gt;trigger();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0triggerLuaCallback(sEventName);\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\n\/\/ On d\u00e9clenche avec un param\u00e8tre\r\nvoid EventManager::triggerEvent(const std::string&amp; sEventName, DataParameters&amp; p)\r\n{\r\n\u00a0\u00a0 \u00a0if (m_events.count(sEventName) &gt; 0)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Event* pEvent = m_events[sEventName];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pEvent-&gt;setParameter(p);\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pEvent-&gt;trigger();\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0triggerLuaCallback(sEventName, p);\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\nvoid EventManager::triggerLuaCallback(const std::string&amp; sEventName)\r\n{\r\n\u00a0\u00a0 \u00a0\/\/ todo\r\n}\r\n\r\nvoid EventManager::triggerLuaCallback(const std::string&amp; sEventName, DataParameters&amp; p)\r\n{\r\n\u00a0\u00a0 \u00a0\/\/ todo\r\n}\r\n\r\nvoid EventManager::attachEventTo(Event* pEventToAttach, Event* pChildEvent)\r\n{\r\n\u00a0\u00a0 \u00a0if (pEventToAttach &amp;&amp; pChildEvent)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pEventToAttach-&gt;pushChildEvent(pChildEvent);\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\nEvent* EventManager::getEvent(const std::string&amp; sEventName)\r\n{\r\n\u00a0\u00a0 \u00a0if (m_events.count(sEventName) &gt; 0)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Event* pEvent = m_events[sEventName];\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return pEvent;\r\n\u00a0\u00a0 \u00a0}\r\n\u00a0\u00a0 \u00a0else\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return NULL;\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\nvoid EventManager::setParametersToEvent(std::string sEventName, DataParameters pParam)\r\n{\r\n\u00a0\u00a0 \u00a0Event* pEvent = getEvent(sEventName);\r\n\r\n\u00a0\u00a0 \u00a0SKIP_IF_FAILED_AssertMsg(pEvent == NULL, &quot;pEvent est NULL&quot;)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pEvent-&gt;setParameter(pParam);\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\nvoid EventManager::getEventsNames(std::vector&lt;std::string&gt;&amp; paramNames)\r\n{\r\n\u00a0\u00a0 \u00a0std::map&lt;std::string, Event*&gt;::iterator it;\r\n\r\n\u00a0\u00a0 \u00a0for (it = m_events.begin(); it != m_events.end(); it++)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0paramNames.push_back((*it).first);\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n\r\nvoid EventManager::pushEvent(const std::string&amp; sName)\r\n{\r\n\u00a0\u00a0 \u00a0Event* pEvent = getEvent(sName);\r\n\r\n\u00a0\u00a0 \u00a0AssertNULLPointer(pEvent);\r\n\r\n\u00a0\u00a0 \u00a0std::string sEventName = pEvent-&gt;getName();\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0m_pushedEvents[sEventName] = pEvent;\r\n}\r\n\r\nvoid EventManager::clearPushedEvent()\r\n{\r\n\u00a0\u00a0 \u00a0m_pushedEvents.clear();\r\n}\r\n\r\nvoid EventManager::triggerPushedEvents()\r\n{\r\n\u00a0\u00a0 \u00a0std::map&lt;std::string, Event*&gt;::iterator it;\r\n\r\n\u00a0\u00a0 \u00a0for (it = m_pushedEvents.begin(); it != m_pushedEvents.end(); it++)\r\n\u00a0\u00a0 \u00a0{\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Event* pEvent = it-&gt;second;\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pEvent-&gt;trigger();\r\n\u00a0\u00a0 \u00a0}\r\n}\r\n<\/pre>\n<p>On enregistres les Events comme ci :<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nEVENT_MANAGER-&gt;registerEvent( new OnTextPaste() );\r\nEVENT_MANAGER-&gt;registerEvent( new OnCameraMovementUpwardRight() );\r\n<\/pre>\n<p><strong>R\u00e9sum\u00e9 : <\/strong><\/p>\n<p>L&rsquo;impl\u00e9mentation d&rsquo;un syst\u00e8me d&rsquo;Event est cruciale dans toute conception de jeu vid\u00e9o. Elle permet en effet de modulariser les m\u00e9canismes de jeu et rend le code plus \u00e9l\u00e9gant et plus facile \u00e0 comprendre.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro : Dans la conception d&rsquo;un jeu il est tr\u00e8s important d\u2019\u00e9num\u00e9rer tous les m\u00e9canismes intrins\u00e8ques au comportement du jeu, c&rsquo;est-\u00e0-dire des \u00e9v\u00e9nements du gameplay, du son, de l&rsquo;interface, du r\u00e9seau, de la gestion des collisions et de l&rsquo;IA. Ceci est une premi\u00e8re approche au probl\u00e8me. J&rsquo;ai \u00e9crit un article sur une deuxi\u00e8me approche plus [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/344"}],"collection":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=344"}],"version-history":[{"count":76,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/344\/revisions"}],"predecessor-version":[{"id":2624,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/344\/revisions\/2624"}],"wp:attachment":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=344"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=344"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=344"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}