Game engine event system

Started by
17 comments, last by Prozak 19 years, 1 month ago
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]
Advertisement
http://nebuladevice.cubik.org/
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***.
Look at Doom 3 SDK, there is an interesting Event system implementation.
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?
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...
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.
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]
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 structureEvent.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.

This topic is closed to new replies.

Advertisement