Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have been puttering around with the fundamentals of a Java game engine, and I've reached the point where I'm ready to add in an Event Manager system.

I know, in theory, what an Event Manager should do: Allow Objects to "register" for certain events, and whenever the Event Manager gets notified of an event, broadcast the event to the "registered" listeners.

What I'm stumped on is how to start implementing it.

I haven't been able to find anything online about implementing an event system from scratch (though I'll gladly take any suggested reading!), so I'm looking for input on what the best practices are in this case -- what I should and should not be doing.

For instance, is it really necessary for each of my GameObjects to have a "EventManagner" field? Since all of my GameObjects inherit from a single, abstract parent class, I think I should be able to use a static reference so that there's only one instance of the EventManager, shared between all the game objects. (I do something similar with the Applet that I use to render each object, already)

And then, I suppose I'd have to maintain a collection of some sort for each possible subscribed event - adding and removing GameObjects from the list as needed.

I think it should be possible to make a queue of events that need to be broadcast - in which case I could simply add "EventManager.Update()" to the main game loop, and have the Update() method broadcast the events that occurred at the end of each frame.

Finally, each object would have a HandleEvent(Event e) method, that they could then parse and respond to appropriately.


Does this sound like the appropriate direction towards implementing such a system, or am I way off track and/or missing something quite obvious?

share|improve this question
2  
gamedev.stackexchange.com/questions/7718/… This is a Q/A I gave previously that can help you get started. –  James Oct 10 '11 at 0:17
    
@James Ah - looks like a good link. Thanks! I think I missed that, earlier. –  Raven Dreamer Oct 10 '11 at 2:14
4  
Some additional hints: decide whether some events should actually take effect immediately instead of at the end of the frame, especially if an event handler triggers additional events; think what happens when you get event loops; if you go with a queue, maybe you'll need a priority system, or a way to bypass the queue. –  Sam Hocevar Oct 10 '11 at 10:23
add comment

3 Answers 3

up vote 6 down vote accepted

This can be as simple as you want.

for each object in the subscriber list:
    object.notify(this event) // (or 'HandleEvent' if you prefer)

Don't try and work out what an event manager 'should' do - work out what you need it to do. The rest should follow from there, or at the least, should suggest some more specific questions.

share|improve this answer
3  
+1 for "Don't try and work out what an X 'should' do - work out what you need it to do." In fact, don't add an event manager at all until you feel like you need some decoupled-yet-centralized way to call functions. –  user744 Oct 10 '11 at 21:38
    
@JoeWreschnig Oh god yes =) "work out what you need it to do" This is amongst the top 3 bits of advice any developer should take to heart. –  Patrick Hughes Oct 12 '11 at 15:53
    
At first I wanted to disagree with your second sentence about not adding an event manager because most games can benefit from a decoupled-yet-centralized way to call functions, but then I thought to how many small games I've made that didn't have any sort of event manager. so, yeah –  jhocking Oct 12 '11 at 16:35
add comment

For the EventManager-field, use a static variable. A Singleton for the EventManager would be a great idea, too.

Your approach sounds good, but don't forget to make it thread-safe.

It is good to execute IO-Events before or after the "GameEvent"s, so in one frame every "GameEvent" deals with the same data.

share|improve this answer
    
"Thread-save"? Hmmm –  U62 Oct 10 '11 at 20:39
    
-1 for the entirely unnecessary and unjustified singleton suggestion. –  Josh Petrie Oct 11 '11 at 3:09
add comment

The three essential methods an event system needs is an addListener() method, a removeListener() method, and a method to dispatchEvent(). That is, a method objects use to register for an event, a method objects use to un-register, and a method to actually broadcast an event to all the listeners. Everything else is gravy.

As you note, you will certainly need some sort of data structure to keep track of registered listeners. The simplest approach would be an associative array (Dictionary, or an Object in JavaScript) that associates a vector (or simply an Array depending on the language) with an event. That vector is a list of all the registered listeners; add listeners to the list or remove them in the add/removeListener() methods.

To broadcast an event in dispatchEvent() it can be as simple as looping through the vector. You could add more complexity to dispatching by sorting the priority of events or whatever, but don't worry about that until you need it. In many cases you won't need it.

There is a little nuance to dispatchEvent() when you consider what data to pass along with the event. At the most basic level you might not pass any additional data; all the listener has to know is that an event happened. However most events have additional data that go with them (eg. where the event happened) to you'll want to have dispatchEvent() accepting and passing along some parameters.

For instance, is it really necessary for each of my GameObjects to have a "EventManagner" field? Since all of my GameObjects inherit from a single, abstract parent class, I think I should be able to use a static reference so that there's only one instance of the EventManager, shared between all the game objects.

There are many ways to give all your game objects a reference to the EventManager class. A static reference is certainly one way; another is with a Singleton. Both of those approaches are pretty inflexible however, so most people around here recommend either a service locator or dependency injection. I've been doing dependency injection; that does mean a separate EventManager field for each object, which is what you seem to want to avoid, but I'm not sure why that is a problem. It's not like there's a lot of overhead from storing a bunch of pointers.

share|improve this answer
1  
+1 for a truly useful example of dependency injection –  Patrick Hughes Oct 12 '11 at 15:48
    
yeah, the first time I really grasped and implemented dependency injection was for an EventDispatcher object. Once I got that under my belt, I've been itching to refactor lots of stuff with that pattern. –  jhocking Oct 12 '11 at 16:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.