9
\$\begingroup\$

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, 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 game objects to have an EventManager field? Since all of my game objects 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 Event Manager, shared between all the game objects. I do something similar, with the Applet, that I use to render each object, already.

I suppose I'd have to maintain a collection of some sort for each possible subscribed event - adding and removing game objects 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?

\$\endgroup\$
3
  • 2
    \$\begingroup\$ gamedev.stackexchange.com/questions/7718/… This is a Q/A I gave previously that can help you get started. \$\endgroup\$
    – James
    Oct 10, 2011 at 0:17
  • \$\begingroup\$ @James Ah - looks like a good link. Thanks! I think I missed that, earlier. \$\endgroup\$ Oct 10, 2011 at 2:14
  • 4
    \$\begingroup\$ 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. \$\endgroup\$ Oct 10, 2011 at 10:23

4 Answers 4

7
\$\begingroup\$

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.

\$\endgroup\$
3
  • 3
    \$\begingroup\$ +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. \$\endgroup\$
    – user744
    Oct 10, 2011 at 21:38
  • \$\begingroup\$ @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. \$\endgroup\$ Oct 12, 2011 at 15:53
  • \$\begingroup\$ 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 \$\endgroup\$
    – jhocking
    Oct 12, 2011 at 16:35
3
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$
    – jhocking
    Oct 12, 2011 at 16:29
0
\$\begingroup\$

DISCLAIMER

Im not a Java programmer but i wrote an article explaining how to create an event system in C89, one of the easiest languages (IMHO), check it out

https://prdeving.wordpress.com/2017/04/03/event-driven-programming-with-c-89/

The basics of event handling are pretty simple.

  • register an event with a callback
  • trigger event
  • loop through listeners to see if there's a match
  • fire handler if found
  • repeat

Knowing this (but not knowing how to implement it in Java), is easy to understand that you need some handlers (functions to handle the events) and add them to an array (with pointers, in C) paired with an event name. Once you trigger an event, you store the triggered event name and it's arguments in a stack, this is called the event pool.

Then you have an event digest (a simple loop), who pops the first event in that stack, tries to find a handler for it, and if theres any, runs it with the params.

Of course, this event digest can be triggered whenever you want, for example once per frame after you call your Update() function.

\$\endgroup\$
-2
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ "Thread-save"? Hmmm \$\endgroup\$
    – U62
    Oct 10, 2011 at 20:39
  • \$\begingroup\$ -1 for the entirely unnecessary and unjustified singleton suggestion. \$\endgroup\$
    – user1430
    Oct 11, 2011 at 3:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .