| | 1 | = Event-Handler = |
| | 2 | |
| | 3 | Maintainer: Patrick Boenzli, boenzli at orxonox.ethz.ch |
| | 4 | |
| | 5 | == Overview == |
| | 6 | |
| | 7 | All files used for event handling are located in the {{{./src/util/event}}} directory. Here a short overview: |
| | 8 | * {{{event_handler.{cc, h} }}} - this is where all the event handling is going on: signals from the SDL env are interpreted and transmitted to the registered event listener |
| | 9 | * {{{event_listener.{cc, h} }}} - this is an abstract class. A class that extends it will have to implement all abstract functions ({{{process(...)}}}) and will be able to register itself to the EventHandler to receive events. |
| | 10 | * {{{event.{cc, h} }}} - a small class representing an event, that has occured |
| | 11 | * {{{key_mapper.{cc, h} }}} - a parser, that reads in the {{{orxonox.conf}}} file and translates the keynames to key-ids used in orxonox |
| | 12 | * {{{key_names.{cc, h} }}} - a file containig all key names with key-ids |
| | 13 | |
| | 14 | == Usage == |
| | 15 | The usage of the !EventHandler System is realy stright forward: consider a case, where you have a !PNode, that wants to receive some key-events: [[br]] |
| | 16 | The {{{pilot_me.h}}} could look like this: |
| | 17 | {{{ |
| | 18 | #!cpp |
| | 19 | #include "p_node.h" |
| | 20 | #include "event_listener.h" |
| | 21 | |
| | 22 | class Event; // forward declaration of a Event class |
| | 23 | |
| | 24 | class PilotMe : public PNode, public EventListener // extending EventListener |
| | 25 | { |
| | 26 | PilotMe(); |
| | 27 | virtual ~PilotMe(); |
| | 28 | |
| | 29 | void process(const Event &event); // abstract process class |
| | 30 | |
| | 31 | }; |
| | 32 | }}} |
| | 33 | The {{{pilot_me.cc}}} class could look like this: |
| | 34 | {{{ |
| | 35 | #!cpp |
| | 36 | #include "pilot_me.h" |
| | 37 | #include "event_listener.h" //the event listener interface |
| | 38 | #include "event.h" //the event structure |
| | 39 | |
| | 40 | PilotMe::PilotMe() |
| | 41 | { |
| | 42 | EventHandler::getInstance()->subscribe(this, ES_GAME, SDLK_LEFT); //subscribe this class to the left-key |
| | 43 | EventHandler::getInstance()->subscribe(this, ES_GAME, SDLK_RIGHT); //subscribe this class to the right-key |
| | 44 | } |
| | 45 | |
| | 46 | PilotMe::~PilotMe() |
| | 47 | { |
| | 48 | EventHandler::getInstance()->unsubscribe(this); //just unsubscribe all subscribtions of this class |
| | 49 | } |
| | 50 | . |
| | 51 | void PilotMe::process(const Event &event) |
| | 52 | { |
| | 53 | if( event.type == SDLK_LEFT) |
| | 54 | { |
| | 55 | if( event.bPressed == true) |
| | 56 | // whatever you want to do, when the left button is pressed |
| | 57 | else |
| | 58 | // whatever you want to do, when the left button is released |
| | 59 | } |
| | 60 | else if( event.type == SDLK_RIGHT) |
| | 61 | { |
| | 62 | if( event.bPressed == true) |
| | 63 | // whatever you want to do, when the right button is pressed |
| | 64 | else |
| | 65 | // whatever you want to do, when the right button is released |
| | 66 | |
| | 67 | } |
| | 68 | } |
| | 69 | }}} |
| | 70 | As you have seen, the whole event-management system is very simple, let's review all the necessary steps: |
| | 71 | 1. Extend {{{EventListener}}} with any class that want to receive events. |
| | 72 | |
| | 73 | 2. Implement the {{{void process(const Event &event);}}} function. |
| | 74 | |
| | 75 | 3. Subscribe for an event {{{EventHandler::subscribe(EventListener* el, elState state, int keyID)}}}.[[br]] You will find the complete list of all SDL Commands in the {{{usr/include/SDL/SDL_keysym.h}}} file. Orxonox has extended the list with some other events, that you will find in {{{./src/util/event/event_def.h}}}. The {{{elState}}} describes the state of the event handler: When the menu is displayed, there are is a diffrent key mapping than when you are playing the game. So this means that there are different states of the eventhandler: {{{ {ES_GAME, ES_MENU, ES_ALL} }}}. So if you subscribe to an event for the state {{{ES_GAME}}} this event will only shoot, if the eventhandler is in this state. |
| | 76 | |
| | 77 | 4. Don't forget to unsubscribe the event again via {{{EventHandler::unsubscribe(EventListener* el)}}}[[br]]. If you forget to do this, there will be a reference to an object that is probably not existent anymore, this will most certanly cause a segfault :D |
| | 78 | |
| | 79 | |
| | 80 | == Advanced == |
| | 81 | There is some more stuff to say :D. Its possible to define !KeyAliases in the {{{orxonox.conf}}} file. These aliases are wrapped in the {{{KeyMapper}}} class and are available from this class as static variables: Eg: |
| | 82 | * {{{KeyMapper::PEV_UP}}} - is the Up Key defined in the config file |
| | 83 | * {{{KeyMapper::PEV_FIRE1}}} - is the fire button defined in the config file |
| | 84 | * {{{KeyMapper::PEV_VIEW0}}} - is the view nr zero key |
| | 85 | * ... |
| | 86 | To see the whole list (and to extend it) read the {{{./src/util/event/key_mapper.{cc, h}}}} files, they are very short. To subscribe to such an event, you can use the code from above and alter it just a little: |
| | 87 | {{{ |
| | 88 | #!c |
| | 89 | //subscribe this class to the orxonox.conf left |
| | 90 | EventHandler::getInstance()->subscribe(this, ES_GAME, KeyMapper::PEV_LEFT); |
| | 91 | //subscribe this class to the orxonox.conf right |
| | 92 | EventHandler::getInstance()->subscribe(this, ES_GAME, KeyMapper::PEV_RIGHT); |
| | 93 | }}} |
| | 94 | |
| | 95 | == References == |
| | 96 | To see more references, look at some source code files, eg: |
| | 97 | * {{{./src/world_entities/camera.{cc, h} }}} - the camera can change the view by pressing some keys |
| | 98 | * {{{./src/world_entities/player.{cc, h} }}} - the player shoots and changes location |