Programming Techniques:Events

From GPWiki
Jump to: navigation, search

Overview

Event driven programming is a paradigm useful for abstracting events and allowing your game to react accordingly to them. This is different from Flow-Driven Programming, which is more linear consisting of a clear path from start to finish.


An event driven model gives two major advantages:

  • Events provide a level of abstraction away from user input. This makes it easier for games to handle input from a variety of locations since your mouse and keyboard class can send a user movement event just as easily as your winsock network class.
  • Passing data between classes becomes easier and more natural as each class is given the ability to listen for relevant events.

Events

Events are normally transfered using a struct that defines the type and provides data specific to that operation. The event type is normally grabbed from an enum and the associated data needs to be general enough so that all event handlers can send and receive data specific to their task. This can be done by storing the data on the heap and type-casting it based on the event type or by creating a group of event dispatchers (one for controls, one to change game states, etc...).

 struct Event
 {
   EventType Type;
   void* Data;
 };
 
 enum EventType
 {
   // Mouse button events. Each of the next six events gets passed
   // the absolute position of the mouse
   E_MOUSELEFTBUTTONPRESS, 
   E_MOUSELEFTBUTTONRELEASE,
 
   // Start new games
   E_NEWGAMEEASY,
   E_NEWGAMENORMAL,
   E_NEWGAMEHARD,
 
   // Game play related
   E_INCREMENTSCORE,
   E_PAUSEGAME,
   E_CONTINUEGAME,
   E_GAMEOVER,
 
   // Close the App
   E_APPCLOSE
 };

The Event Dispatcher

The event dispatcher is normally a Singleton object that keeps a list of all event handlers and notifies them of an event. There are several different methods for doing this, some involving event queues, interrupts, or the simplest type of event dispatcher immediatly sends out events as soon as it receives them.

Since this is just an introduction the example provided will describe the latter type of event dispatcher. This example is not thread-safe and is easy to overload if a large number of event handlers are to be used.

#include <vector>
 
class EventDispatcher {
 
public:
  // Adds an event handler to the vector list
  void AddHandler(IEventHandler *handler);
 
  // Sends an event to all of the event handlers
  void SendEvent(Event* event);
 
  // Methods to clear the list or manage priorities can also be added
 
private:
  vector<IEventHandler*> ml_handlerlist;
};

The Event Handler Interface

The event handler responds to events sent out by other functions through the event dispatcher.

class IEventHandler {
 
public:
  virtual void HandleEvent(const Event &e) = 0;
 
  IEventHandler() {
    // Self-Register with the event dispatcher upon creation
    EventDispatcher::GetInstance()->AddHandler(this);
  }
};

Example

class MyClass : public IEventHandler {
 
protected:
  void SendEvent(EventType eventType, char arg1 = 0, char arg2 = 0) {
    // Create and load your data object
    char *_data = new char[2];
    _data[0] = arg1;
    _data[1] = arg2;
    // create the event and load the event type and data
    _event = new Event();
    _event.Type = eventType;
    _event.Data = _data;
    EventDispatcher::GetInstance()->SendEvent(event);
  }
};

Will add more soon

Conclusion

Will add more soon

External Links