   How to design an event driven architecture for a game ?
  I am trying to find a better way to do this in a game.Scenario: Player fires a bullet which hits the monster. This generates an event(Event_Bullet_Monster). I want multiple systems listening to various events, and handle them accordingly.My Approach:When CollisionMgr detects the monster has been hit by the bullet, it invokes EventManager.handleEvent(bullet, monster).EventManager::handleEvent(obj1 , obj2):EventManager mantains a hashMap of <(name, name), EventObject>EventManager mantains a hashMap of <EventObject.Type, List<Listeners> >so based on the name of obj1 and obj2, it instantiates the right eventObject (in this case,Event_Bullet_Monster). It further looks up eventObject.Type on a map and invokes listener.Update(Event_Bullet_Monster) for each of the registered listener.Listener::Update(Event event) : Either I have a lookup in here which looks like this: or I do a if-else construction going through all the possible event.I am sure this design can be improved a lot, just that I can't think of a better way to handle these events. I also heard something of the likes of event-aggregator concept.I'd appreciate any thoughts on this.Thanks
  I strongly reccomend you take a look at "Game Coding Complete" (book). It has an excellent event system described in there. There is also code for it availible online (though I can't recall the url).What I may do would be to create a new event, EventMonsterHit or some such with details of the hit. I'd then queue it with the event manager (theres also the option to handle it immediatly rather than queueing).Any class that inherits from IEventListener can register itself with the event manager and listen for events (each different type of event is registered seperately so you only hear what you want to hear). Once per game update the event manager dispatches any events to any event listener interested in that event type via a HandleEvent method in each class.As you may well have alot of events, each event type has an HashedString rather than an enum or some such as identification. Its far more versitile than an enum but it does mean HandleEvent can't use a switch statement and must do if else if (can get nasty looking with alot of events).Check out the book, definately worth it.   ;As you may well have alot of events, each event type has an HashedString rather than an enum or some such as identification. Its far more versitile than an enum but it does mean HandleEvent can't use a switch statement and must do if else if (can get nasty looking with alot of events).I'm sorry to kidnap this thread, but my question is tightly related to it, to the quote ^I'm not sure I fully understood the concept of HashedStrings for identifiers (or game objects or events or whatever). Using string identifiers require the code to do string comparisons, which is bad. Hash is a number and numbers are compared MUCH faster. Do I get it right that the use of hashedstring moves from "compare the given string with other strings" to "compute hash and compare the hash with other hashes"? Is the point in the assumption that with string identifiers it would have to compare quite a lot of strings (if you have a lot of objects/events etc.), which would be slower than computing the hash and then comparing just integers?   ;Using string identifiers require the code to do string comparisons, which is bad. Hash is a number and numbers are compared MUCH faster. Do I get it right that the use of hashedstring moves from "compare the given string with other strings" to "compute hash and compare the hash with other hashes"? Is the point in the assumption that with string identifiers it would have to compare quite a lot of strings (if you have a lot of objects/events etc.), which would be slower than computing the hash and then comparing just integers?Yea Tom, that would be correct. Depending on your situation, you can generate the hash accordingly. One possible way is:int static MySpecificEvent::GetHashValue(){ static int value = "MySpecificEvent".hashValue(); return value;}This way, hash is only calculated once per event-type and you get an int in bargain which happens to faster to compare.   ;  But this way I would need a separate object definition for every event, which is very close to just using an enum, isn't it?If I wanted to use just the strings in my code, when I want to do something with an entity called "WeaponBox54" or send an event "WeaponBoxOpened", the hash needs to be calculated every time I use the string, am I right?   ;But this way I would need a separate object definition for every event, which is very close to just using an enum, isn't it?Its a design decision. No system is perfect, its just the way you architect it for your needs/games. Design can give you an idea of how to solve the problem, but adapting it to your own game is something you'll have to do by yourself. For me, I am making every event different, and yes I intend to have different objects for each type of event.If I wanted to use just the strings in my code, when I want to do something with an entity called "WeaponBox54" or send an event "WeaponBoxOpened", the hash needs to be calculated every time I use the string, am I right?static int value ="MySpecificEvent".hashValue();<br />It will only be calculated once since it is in a static initialization.;static int value ="MySpecificEvent".hashValue(); It will only be calculated once since it is in a static initialization.Yes, but my point was that MySpecificEvent is a name of a class. When I decide to add MyOtherSpecificEvent, I must add its definition and all modules of my game which are using events will need to be recompiled because they are probably including the .h file which has changed.That's why I mentioned using strings in the code, in which case the hash has to be computed everytime. Something in the sense of:eventManager.AddEvent(GetHashFromString("MySpecificEvent"));But I repeat - I've never done it, in my small recent project I've used just string identifiers for objects and resources, in a std::map (performance was not a problem). Now I'm starting to improve my "engine" and am still (even after reading a great book Game Engine Architecture) not sure how it really works. Nobody never mentions how it looks when you want to access a specific object/event identified by the hashed string.   ;Yes, but my point was that MySpecificEvent is a name of a class. When I decide to add MyOtherSpecificEvent, I must add its definition and all modules of my game which are using events will need to be recompiled because they are probably including the .h file which has changed.That's why I mentioned using strings in the code, in which case the hash has to be computed everytime. Something in the sense of:Well, if you make myspecificEvent in its own header class, and then wherever you use it (in other classes), you will need to recompile that part of the code anyways. All of the modules shouldn't need to be recompiled since it is not dependent on other modules. Maybe, I am not understanding your point here.eventManager.AddEvent(GetHashFromString("MySpecificEvent"));But I repeat - I've never done it, in my small recent project I've used just string identifiers for objects and resources, in a std::map (performance was not a problem). Now I'm starting to improve my "engine" and am still (even after reading a great book Game Engine Architecture) not sure how it really works. Nobody never mentions how it looks when you want to access a specific object/event identified by the hashed string.I've felt like that before, but I reached a point where I started writing my own stuff and asked around how could I improve it (just like this one) . I think this is how it really works. Also, from the code you wrote...How about this:(E.g. Player is trying to register a event bullet fired:)void Player::OnFire(){ // ... EventManager.HandleEvent(new BulletFired(pBullet)) );}// this will not make EventManager to be recompiled, only Player!now in EventManager::HandleEvent(Event* event):List<Listener> listeners = m_lookup[ event->GetHashValue() ];foreach listener: call listener->execute(event);definition of Event:class Event{ virtual int GetHashValue(){ static int val = "Event".hashValue(); return val;}}class Bullet_Fired : public Event{ virtual int GetHashValue(){ static int val = "BulletFired".hashValue(); return val;}}In all of this, only the class where you identify Bullet_Fired will be recompiled. Player will be recompiled since it has a change. But EventManger will stay as is and not be required to recompile.Hope this helps.   