Since the subject has been discussed recently I though I woudl post a few of the considerations to keep in mind when writing an event driven game engine.
The core concept in an event driven game engine is the message loop. Similar to the windows message loop, in which the game keeps a list of things to do each iteration of the game. One big difference though is that modern event driven game engines use a second message loop for things that will occur in the future, but do not need to be checked every iteration. e.g. If you click on a factory to build a unit, the event to create the unit will occur at some point in the future, lets say 10 seconds, but you dont need to check whether that 10 seconds is up every game tick, which woudl mean you checked if it was time to create the unit some 300 times before it was actualyl time to create it (at 30fps). So there are two event loops, or lists. The events that must be processed every game tick, such as updating a units position, rendering it on screen, etc. and the events that only need to be processed when their timers expire, such as unit creation.
So the game engine has a linked list of enents called the main event loop. Each event has a type. The event loop pulls the first eent off the list and processes it. It then deletes teh event object and procededs tot he next event in the list. It continues to do this until it either reaches the end of teh event list, or processes a QUIT event. As I will explain, a properly written event loop will never reach teh end of the event list. The first event type I will explain is the Render Game State event. It sounds pretty obvious that this event renders teh buffer onto the screen, but it also does more than that. It also adds a new Render Game State event to teh back of the event list. So that there is always an event on the list that will render the current game state. This is a self refreshing event and many events are of this type. The QUIT event will cause teh game to immediately terminate as if it recieved a WM_QUIT message. This is used to shut down the game in responce to e.g. the player hittign the exit button on a menu. So when teh application starts up, the initialization code would place the Render Game State event on the loop. The next event type that some engines use is the Process Windows Messages event, which iterates through all pending WM_ messages and processes them. Personally I dislike this as it locks the mouse and keyboard processing to yoru frame rate. I prefer to write teh message loop so that it processes any pending windows messages each iteration, and then processes a game event, then checks again fro pendign windows messages. This does create a small amount of overhead as you are pollign for windows events much more often, but the overhead is very minor, and it creates just awesome responsiveness, which teh player will appreciate. The next event Id like to discuss is Process Timed Event. This is also a self refreshing event, and it causes the engine to check the timed events (e.g. the create unit event mentioned earlier). The timed event list must always be kept sorted so that the first item on the list will expire first. This way the engine needs only check the first item, if it hasnt expired it can simply ignore all other events on the timed event list, saving a lot of processing time. There are several variations of how the engine handles an expired event. Some engines immediately process the item, some move it to the top of the main event list so that it gets processed later. There is also some variation in what the engine does next. Some engines only process the first item, others continue checking for for expired items. The benefit of processing one item only is that if a large number of events expire simultaneously it will not cause a noticeable lag in the games frame rate, as only a single event is processed per frame. The drawback is that if the game is generating more than 1 timed event per frame for an extended period of time, the backlog can cause anomalies like units not being created for several seconds after they are finished. I could write a PhD thesis on all the trade offs and optimizations that are possible, but I'll save that for my PhD thesis.
But what about the units themselves. Well, each unit gets its own event, which is the Update Unit event. This usually self refreshing event updates the physics of the object, renders it to the buffer, and conditionally creates a new event on the loop. I say conditionally because if the unit is dead or needs to be deleted, it adds a different event, the Delete Object event, and does not refresh the Update Unit event. In a similar manner, the Create Object event when processed does not refresh itself, but instead adds an Update Object event.
Now I need to take a moment here to explain what the events themselves look like in memory. The event loop is basically a linked list of pointers to an Event structure. The event structure is just a value for the event type, and a pointer or other data to any information necessary to process that event.
Anyhow, as the events are processed and refreshed the loop will always have some events in it. The frame rate is basicalyl how fast it can process all teh events in the loop between one occurance of the Render event, and the next. If we had 3 objects in teh list the loop migth look like this to begin -
Check Timed Events
and after it processed one event it would look like -
Check Timed Events
and would continue. It is important to note that the UI code can insert and delete events based on the players inputs. This loop basically just processes the physics, it doesn't handle the UI, which would be done through the windows message loop.