• Advertisement
Sign in to follow this  

Game engine event system

This topic is 4721 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Im looking at starting a C++ OO game engine, this time im going to try to plan all parts from the beginning rather than just coded random stuff that I feel like doing. I am looking at the best way to organise a game, and an event/messaging system appealed to me. But im not entirely sure how to implement one in a game. I found an article on this site which showed a very basic implementation of one but i would like a more in depth article on it. Does any one have any other articles or book suggestions on event/messaging systems? I think I understand that different parts of the engine should be able to register to listen for certain events and when that event is fired off from some other part of the engine that class will be notified and will handle it accordingly. Should everything in the game be based on events?

Share this post


Link to post
Share on other sites
Advertisement
Hi.
I did this myself for an engine and think it's a good idea to have it. You will get a clean design and a good abstraction.

For example:
If you have a collisuion, the collision manager just sends a collisionEvent, then other parts of the system/managers that are interested just listens to the collision-node etc.

I used a basic Node class (like a quadtree) and have a tree based eventsystem, where you can listen on several levels and several points.
Every node can have Events and listener registered to them.
For the events I just use a abstract base class which all eventclasses inherit from.
So every manager or objekt in the system can create nodes, events and listen.

First I had some problems with the performance. Since you could create.. say a hundered events on a single frame, the dynamic allocation is bad for the performance and also will get the memeory fragmented.
I fixed this by Implementing a MemoryPooling system so the object memory gets reused and I have no realy problems with perf and stuff anymore.
You will anyway have good use of a memory system later when dealing with particle systems and things.


/martin

Share this post


Link to post
Share on other sites
Maybe use the window's messaging system if your using that os, thats what im thinking of doing...

anyone reakon that would be a bad idea?

Share this post


Link to post
Share on other sites
Quote:
Original post by johnnyBravo
Maybe use the window's messaging system if your using that os, thats what im thinking of doing...

anyone reakon that would be a bad idea?


Yes. It kills your ability to make things cross-platform.

Share this post


Link to post
Share on other sites
Quote:
Original post by schlinge
I used a basic Node class (like a quadtree) and have a tree based eventsystem, where you can listen on several levels and several points.
Every node can have Events and listener registered to them.
For the events I just use a abstract base class which all eventclasses inherit from.
So every manager or objekt in the system can create nodes, events and listen.


Could you maybe elaborate a bit on this? It sounds very nice.

Share this post


Link to post
Share on other sites
The basic message system is simple, but you have to make a few design choices before you try and lay things out.

You first need to decide how tightly you want to couple your systems; you could actually define very loosely coupled systems that export just the message system. I'd probably only do this for objects outside of the core though, using it to attach entities to the game.

Another choice to make is how you want the messages to be passed around the system; do you want the messages to be propagated down a heirarchy of objects, with the object choosing to react to the message or not? Or do you want the message system to specifically target an object by it's ID? (Perhaps using a signal/slot system).

You should also consider how you'll manage the sequence of the messages, in some instances it's important that messages come in sequence so that you're not trying to revive dead players with health packs and the like. This is especially important if you choose to tie your message system up to your network system.

Other sticky choices I've been facing is how the receiver should be able to respond to the sender. Should it be able to respond directly or should it be able to respond by pushing it's response in the message queue? How about times that you want to propagate messages up the tree from the leafs to the roots? If you will need this, you'll have to design your system accordingly.

You should also look into systems like sigslot, if at least as a way of playing around. I prefer my hand-rolled system to sigslot (I like my message param system) but it could save you a bunch of work in getting up and running.

This is my current area of study, so I apologise if I'm getting carried away ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by schlinge
I used a basic Node class (like a quadtree) and have a tree based eventsystem, where you can listen on several levels and several points.
Every node can have Events and listener registered to them.
For the events I just use a abstract base class which all eventclasses inherit from.
So every manager or objekt in the system can create nodes, events and listen.


Wow, that sounds like my current implementation too. Each 'entity' is effectively a node that can receive messages; depending on the handlers attached to it and it's default relay proc it'll pass the messages down it's tree of attached entities. The main thing I'm building in now is a FSM to allow the user to switch siwtch on/off the responses to these messages depending on the entitiy state.

Share this post


Link to post
Share on other sites
Quote:
Original post by bossmonkey666
I think I understand that different parts of the engine should be able to register to listen for certain events and when that event is fired off from some other part of the engine that class will be notified and will handle it accordingly. Should everything in the game be based on events?


I wouldn't say everything, for game engine itself there probably wont be many besides. Personally i think a message based system is a little too indirect for just the internals of a game/engine i would suggest an event system based on callbacks or observer design pattern and nice idea is to use a signals & slots framework if your using C++ the boost libraries has such a framework you can see that here.

Share this post


Link to post
Share on other sites
i agree with snk_kid.
I am using signals/slots, smart pointers (shared_ptr) and boost's graph system for my vis-engine.
I totally would recommend it to everyone who is programming in C++.

Share this post


Link to post
Share on other sites
Thanks, I think I will try out the boost signals thing. It looks relatively easy to implement so it should save me a lot of time. When I get more comfortable with the idea of an event system and I have a bit more time I might try creating my own but the boost signals look like they will work for me for now.

Share this post


Link to post
Share on other sites
Hmmmm....

I can tell you how i did my engine's event system. Basicly you used a call to register a new Event, like so:
Events.Register("window_close");

Other code can hook itself onto this Event by doing the following:
Events.Hook("window_close", function_ptr);

The function pointed to in function_ptr will be called when the "window_close" event is triggered.

All we're left with is to trigger the event itself, which we accomplish with this code:
Events.Trigger("window_close");

All functions that had hooked themselfs onto the event would be called in sequence.

Although the calls themselfs are simple, and simplify the whole process, there is some tricky stuff in the background. For one, we don't know beforehand how many functions will hook themselfs onto a certain Event, therefore we need some sort of linked-list to hold the hook data.

Another point is that we create name events using strings, which requires a fast method to sort them, and search them.

I would also like to add that there is a null pointer assigned to each event, and it is free to point to whatever you want, which becomes usefull to use as a parameter passing device to the events triggered. You just point it to a structure holding your parameters, and the triggered functions can then point to that structure too.

This has worked very well for me, and I hope my explanation of how I did can help you design yours. Good luck with your project. [wink]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
http://nebuladevice.cubik.org/

Share this post


Link to post
Share on other sites
Quote:
Original post by evolutional
Quote:
Original post by johnnyBravo
Maybe use the window's messaging system if your using that os, thats what im thinking of doing...

anyone reakon that would be a bad idea?


Yes. It kills your ability to make things cross-platform.


Not to mention it is slower than s***.

Share this post


Link to post
Share on other sites
Look at Doom 3 SDK, there is an interesting Event system implementation.

Share this post


Link to post
Share on other sites
Quote:
Original post by Prozak
Another point is that we create name events using strings, which requires a fast method to sort them, and search them.


Is there a special reason you are using strings instead of a large enum? I assume that it's easier to create new events using strings, and that that is the main reason?

Share this post


Link to post
Share on other sites
I'm using strings because of several factors, internal to my engine.

At first I thought it was a really bad idea, or a bad design implementation, but after a while it made much more sense.

It's much more intuitive to use. When I trigger the "window_close" event I know exatcly what I'm triggering... instead of calling something like:
EventNumber = EV_Window_Close; // #defined Keyword
Events.Trigger(EventNumber);

...buf if I #defined my events, adding new events as the engine grew would be a pain... so the Events had to be easily created.

Because my engine relies heavily on plugins for extensability, the way another coder would access the engine's internal events, and the way the coder would hook its code to mine, required certain logistical things to be designed as they are now.

First of all, Events would have to have a string attached to them, (even if the primary search key was a numeral), so that coders could do a search on the engine's "hookable" Events, and select the one they where interested.

Even though searching for a particular string may be considered a slow thing, hooking to an event usually occurs in "setup" code, code that is seting itself up to do something, and due to that exact nature, it means that that code won't run again, only the receiving function will actually run, so there is really no need for us to worry with the speed of the string search.

None the less, if we have a piece of code that does a lot of Event work, we can search the string only once, and retrieve its handle:
Handle h = Events.GetHandle("window_close");

And then we can just use the handle:
Events.Hook(h, function_pointer);

I'm also planing on creating a self-altering pool of code. The core of an event system is, when a certain condition is met, it triggers the execution of other code. So, we can abstract an event to a list of functions calls. The more functions are hooked onto that Event, the more calls we have to make.

In terms of assembly code, its fairly easy to create a pool of code that calls all the functions of a certain event, and then, when the Event triggers, we can just jump to that piece of dynamic code.

This method is as fast as it can be. The code pool would of course have to be invalidated in case a function Hooks or UnHooks itself from an Event, so the code pool has to be redone...

Those where my 3 cents...

Share this post


Link to post
Share on other sites
I'm currently developing an event system in C++. I didn't hear it mentioned here, so I'm wondering if I'm going in the wrong direction.

Basically, I have a base event class(F_Event) that serves as an interface for the rest of the event types(ie F_Event_Movement or F_Event_FireMissle or the always needed F_Event_SomeoneSetUpUsTheBomb). This interface consists of two functions bool isPossible() and bool trigger(). The constructor of the subclass provides the data for the event.

Each event has a few basic members. An int m_EventID which is used for registering target systems and determining the type of event it is. For instance, a movement is a movement event no matter if it's a F_Event_Movement_MagicMissle or F_Event_Movement_Monkey. Therefore, each would need to know that it's of type "movement" for target systems to recieve all the movement events. I'm toying with the idea that I could have each event store a boolean m_isTriggered value, so that the event knows when it's been completed. The reason why I'd do this instead of just having the event remove itself from the overall event list is so that if multiple systems recieve the same event, one system doesn't remove the event from the list before the second system has a chance to look at it(causing a few null pointer issues). Also, the events would have a pointer to the EventSystem so that they could retrieve things such as current time or external data which they might not have available to them on creation.

Finally, there would be an all powerful F_EventSystem that'd store and dispatch all the events. Here, you could register targets for events EventSystem.registerTarget(eventID, target). The EventSystem has all the data needed for events that need external access to other data.

I believe that it was Schlinge that said memory would become too fragmented with this many events being dynamically allocated. I'm not too terribly sure how to work around that issue. I don't know of any other way to create or destroy events.

Anyways, if this seems like poor form, I'd love to know the proper way to do this.

Share this post


Link to post
Share on other sites
Quote:
Original post by Prozak
...
Events.Hook("window_close", function_ptr);
...
Events.Trigger("window_close");

...


This may be a dumb question, but using your example, how does your message system know *which* window to close (assuming there is more than one)?

Thanks for any further explaination.. [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by code4fun
Quote:
Original post by Prozak
...
Events.Hook("window_close", function_ptr);
...
Events.Trigger("window_close");

...


This may be a dumb question, but using your example, how does your message system know *which* window to close (assuming there is more than one)?

Thanks for any further explaination.. [smile]


You create a structure, which each of the receivinf functions will understand, and then you fill out that Event's parameter pointer.

When the function receives control, due to "window_closed" having fired, all that that function needs to do is use the strcture to point to the correct memory address, and get all the info it require from there.

Something along these lines:
struct s_window
{
HWND myWindowHandle;
char *WindowName;
};

int function omg_mywindow_isclosing()
{
s_window * sw;
sw = (s_window*)Events.GetParameter("window_closed"); // Returns a pointer

// Insert Logic code here
(...)

// We can abort any further hooks from receiving this event, by returning -1
return 0; // all ok
};


main()
{
s_window sw;

sw.myWindowHandle = this->windowHandle;
WindowName = "Main Window";

Event.SetParameter("window_close", &sw); // Pass a pointer to our structure
Event.Trigger("window_close"); // Trigger all the Hooks
};


Keep in mind this is just an example, I'm discussing more software design than actual code here.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement