Event sequencing issues.

Started by
1 comment, last by MeshGearFox 14 years ago
I'm working on a simple turn-based 2D game engine in C++/SDL that treats game entities as such: Each entity in the level has a personal event queue, which lists events that are done to the entity. These map to lua functions. Each entity also has an update function. When the update function is called, every event in that entity's event queue is run, followed by some sort of default behavior. Level entities are stored in a list. In the program's update loop, which handles game logic (I'm using a setup sort of inspired by XNA, I guess), the list is iterated through in a linear fashion, running every entity's update function in sequence. Typically, events are generated by one entity interacting with another. For example, if the player walks onto a pressure plate, it would generate a stepped_on event for the pressure plate, which would then unlock a door somewhere, or something like that. One obvious problem with this setup: Because the entities are updated in a linear fashion, if an event is generated on an entity who has already been updated, the entity will not handle that event until the next turn. Continuing from the previous example, if the pressure plate was stored in the list before the player, then it would not unlock its associated door until the next turn--at which point the player would have already stepped away from the plate, leading to a very bizarre and confusing sequence of events. How might I ensure that every event that occurs within a single turn is handled that turn? I had a few ideas, but they seem off. 1. Have a flag that's set every time something has an event added to it, and is set to zero at the after every complete iteration through the entity list. Re-update every entity with a non-empty queue until this flag is no longer set. Problem: Possibly slow and doesn't take the proper order that the events were triggered in into account. 2. Have a queue of entity IDs. Every time an entity has an event added to it, push its ID onto the queue. Keep running update for entities in the ID queue if they have a non-empty event queue. 3. Do the same thing as above, only have a queue of pointers to the entities in question. I'm actually sort of leaning towards this.
Advertisement
Quote:Original post by MeshGearFox
Because the entities are updated in a linear fashion, if an event is generated on an entity who has already been updated, the entity will not handle that event until the next turn.


Do you update the entities each frame or each turn? If it's the former, then the event will be triggered on the very next frame, so I probably misunderstood something.

Also, it sounds like you're not using the usual Observer-style of event handling. I'm not sure why you're adding events to a queue to be processed later, rather then handling the event when it happens.

In the door/plate example, the door can be a listener of the plate. When ever you detect that the plate has been stepped on, the plate triggers a "stepped on" event, which notifies the door, which opens itself in response.
That's actually a very good question. I updated all of the entities and then redrew the entire screen afterward, as opposed to updating a single entity and then redrawing.

Quote:In the door/plate example, the door can be a listener of the plate. When ever you detect that the plate has been stepped on, the plate triggers a "stepped on" event, which notifies the door, which opens itself in response.


Hm. In my current setup, what would happen is this:

When the player moves, a collision detection manager checks to see if they moved into a space occupied by a pressure plate. When this happens, the pressure plate immediately has the "stepped on" event added to its event queue.

However, my issue was that I wasn't updating the event queue immediately. An entity's event handling was tied directly to its update code, meaning it'd only get updated once per turn, only handle its events once per turn... and that led me to my problem.

I think I came up with a solution. It's working right now, in any case.

1. I separated the update code and event handling code. Just for code sanity purposes, this really needed to be done.
2. I went with that third option I was talking about in my first post. Every time an entity has an event pushed onto its event queue, it adds a pointer to itself to a queue of entities that need to have their events handled.
3. The update function now works as such: An entity performs its default behavior. After doing this, the update function checks to see if the previously mentioned queue has anything in it that needs updated. If it does, those entities are updated.

This topic is closed to new replies.

Advertisement