# Event This is an implemenation of an Event class in C++. Since C++ has no bult in event structure I created this one to facilitate the ability to assign listener functions for an arbitrary function definition. It utilizes C++ Templates. ## Implementation `Event.hpp` ``` cpp #pragma once #ifndef BIT_EVENT_H #define BIT_EVENT_H #include namespace bit { template class Event { private: std::vector listeners; public: template void trigger(A arg1) { for(unsigned int i=0; i < listeners.size(); i++) listeners[i](arg1); } template void trigger(A arg1, B arg2) { for(unsigned int i=0; i < listeners.size(); i++) listeners[i](arg1, arg2); } template void trigger(A arg1, B arg2, C arg3) { for(unsigned int i=0; i < listeners.size(); i++) listeners[i](arg1, arg2, arg3); } // Registers the listener and returns its ID if it needs to remove it unsigned int operator += (T listener) { listeners.push_back(listener); return listeners.size() - 1; } // Removes a listener by its id void operator -= (unsigned int index) { listeners.erase(listeners.begin() + index); } }; } #endif ``` ## Example Usage In a tile based game a Tile has an event called a `onBodyEnter` which should fire when a character moves onto the tile. Listeners can react to this event. ![](/images/EventDoor.gif) `Tile.hpp` ``` cpp // event definition bit::Event> onBodyEnter; ``` `Tile.cpp` ``` cpp // event firing, body is what has entered the tile onBodyEnter.trigger(this, body); ``` So our tile has the event defined with the function definition that the listeners should be prepared for. When a body enters the tile it triggers the event which iterates its listeners and runs them with the tile and body in context. A listener example is a Door object that sits adjacent to tiles. It wants to know if a body enters an adjacent tile so that it can open automatically. `Door.cpp` ``` cpp void Door::registerTileTriggers(Tile* tile) { Door* d = this; if(tile) { tile->onBodyEnter += [d] (Tile* t, Body* b) { if(b->Body::schema.type == Body::Type::Character) { d->openerCount++; d->attemptOpen(); } }; tile->onBodyLeave += [d] (Tile* t, Body* b) { if(b->Body::schema.type == Body::Type::Character) { d->openerCount--; if(d->openerCount == 0) { d->attemptClose(); } } }; } } ``` The Door registers a listener for the adjacent tile. When fired the lambda operation will attempt to open the door that was listening.