Global Event Manager System

Started by
11 comments, last by Hodgman 11 years, 2 months ago

The main thing Hodgman and I dislike about major global event systems is the abstraction—they basically violate the single-responsibility principle (not to mention the debugging nightmare). It is easy to get carried away with them such that the single system ends up handling all types of events from and to anywhere and anything.

I prefer to divide the workload into related subsections and within those subsections I decide on the best system to use, such as delegates, virtuals, etc. You also mentioned something that I was going to use as a classic example of what often gets treated as event-based but should not be: input.
Actually, proper input handling could be an entire new thread/discussion, and I have been asked to post about it on my blog so I will eventually, but for now we can get straight to one of the big questions left open by an event-based input system: When do you handle those events?
As soon as you detect the button was pressed? Even in single-threaded systems, while the timing may be predictable (it will always happen just before the game cycle update (which could be both a Tick() and a Draw() or just a Draw())) it has problems with fixed-step implementations. If you tell Mario to jump but logical updates won’t happen for another 30 milliseconds, what data do you change? Logic should only happen during a logical update, so adjusting Mario’s jump status and upward velocity between logical updates as the result of an input event is out-of-place.

Then you get into multi-threaded systems where doing these kinds of updates out-of-place is not just a logical fallacy but a bug farm.

On the one hand, good advice is not to over-engineer things. Event systems are often more than what is really necessary for a lot of things. Divide the load into related sub-systems and think about what is really the bare minimum necessary for it to work, and keep options such as delegates and virtuals on the table. The link you posted is somewhat of an event in concept (changing a state and passing data to the new state) but the system was engineered only for that specific task and with those specific classes. Using an abstract and general-purpose event system would get the same results but would be a case of over-engineering.

On the other hand, using events to handle input is actually under-engineering. Smooth and consistent input-handling is a non-trivial task that events alone simply can’t handle.

Separate things into related buckets and think about what is neither too much nor too little.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Advertisement

Which language are you using? I can translate that into C or C++ if you like...

For those of you using C++. How do you implement your delegates?

I've found several resources on the internet:

This looks to be very popular. The code looks insane.

http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates

This is a very novel solution using templates

http://molecularmusings.wordpress.com/2011/09/19/generic-type-safe-delegates-and-events-in-c/

This also looks to be a fairly simple design, using polymorphism.

http://nocturnal.insomniacgames.com/index.php/Common#Event.h (implemented here - https://github.com/HeliumProject/Foundation/blob/master/Event.h)

I know there is also boost::bind and boost::function. Which delegates does everyone prefer?

I know there is also boost::bind and boost::function. Which delegates does everyone prefer?

On an up-to-date C++ compiler, you've got std::bind and std::function, along with the C++ lambda syntax -- so those would be the default choices these days.

Personally, I like to just use C-style function pointers in most situations (and hand written functions to bind them to C++ objects)...

This topic is closed to new replies.

Advertisement