Event dispatching, Event manager for engine core system.

Started by
11 comments, last by HexDump 16 years, 2 months ago
Hi all, I´m thinking about building a little event manager/dispatcher for my engine. I will be using it for example to send messagges between entities, queue timed actions like "remove this entity in ten secs". I will be using this to handle things for comunications between systems, for example input system can notify a "player in the world" about that "Up action" has been produced, etc... I´m kind of new on this, so, I would like to know if there is any paper on this, can anyone give any feedback on this, or in the other hand complain about my dumb idea. Thanks in advance, HexDump.
Advertisement
Boost slots is already made for you :)

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

I assume you mean boost::signals? Boost is great and I've used many parts of it but generic programming is by definition usually too generic (extra overhead for stuff that you really don't need).

Without more refined explanation of how you want your system to work it's hard to give an proper answer. In the system I'm designing currently we use a combination of delegates (google fast delegates), lock free queues and some other weird lock free state changes. This of course wouldn't make any sense if we weren't creating a multi threaded system [wink].
----There he goes. One of God's own prototypes. Some kind of high powered mutantnever even considered for mass production. Too weird to live, and too rare to die.
I've heard Boost::slots are extremely slow.

Like mentioned above, google delegates - or wait for someone else who knows more than I to give a better suggestion.
Hi again,

Well, It could sound stupid, but I don´t really know what I really need.

I feel I need something like a event manager thing that will coordinate all system messages (game level mainly). For example as I said, connecting the player to the input system, sending messages between entities, etc... SO I would like to know if anyone has implemented something like this. What are you using it for, beside the things I told, etc...

Sorry for the vague explanation, but it is diffciult to explain something that you really don´t know how it looks like.

I could make a little list of things I will need to:

1) TImed events (an event that will be fired in x secs, like remove this from world in x secs).
2) Entity events. A entity can tell others about hazards, etc... or where they can find good items, etc...
3) Inter System events. For example, Logic system can send a meesage to the sound system to play sound X.
4) etc...

I don´t know if this is too much overbloated, because, for example insted of 3 I could have sound system as a singleton and just do CSoundSystem::GetPtr()->PlaySound(x).

I guess, this will really depend on my game, and if I aim net game. Anyway, I would like some one to discuss how they do this type of things, if they are usefful or just my view is overbloated/overenginiered.

Thanks in advance,
HexDump.
Quote:I could make a little list of things I will need to:

1) TImed events (an event that will be fired in x secs, like remove this from world in x secs).
2) Entity events. A entity can tell others about hazards, etc... or where they can find good items, etc...
3) Inter System events. For example, Logic system can send a meesage to the sound system to play sound X.
4) etc...


That's not how it works.

In event system, the core are events. They don't tell anyone anything, they trigger, and if someone happens to be listening, they react.

1) Timers are unrelated to events. They can just be implemented via events.
2) You don't query an entity, and it doesn't tell anyone. Player P enters room R. P subscribes to R's events. At some point, R fires "explosion" event. P will be notified, and will do something. In addition, HazardMonitor is also listening to explosion events, and when it happens, it will deal damage to all objects within range
3) Other way around again. When player enters a room, sound system subscribes to it. When player does something, it fires an event. Among others, sound system will receive it.


Pseudo design for this is something like this:
class Player {  void shoot()  {    ammo--;    calculateDamage();    fireGunEvent.fire(getGunType());  }  Event fireGunEvent;  Event moveEvent;};class SoundSystem {  void onEnvironmentEvent(int type, int x, int y, int damage)  {    if (type == BIG_EXPLOSION) {      play("big_explosion.wav");    }  }  void onGunFired(int gun_type) {    if (gun_type == PISTOL) {      play("pistol_shot.wav");    }    if (gun_type == SHOTGUN) {      play("shotgun_shot.wav");    }  }}class Room {    Room()  {    timer.schedule( onExplosion, 15 ); // in 15 seconds, explode  }  void onExplosion() {    // fire big explosion, at 100,150, with 5000 damage    environmentEffect.fire(BIG_EXPLOSION, 100, 150, 5000);    timer.schedule( onExplosion, 15 ); // fire another one in 15 seconds  }  Event environmentEvent;};


Here, each system knows only about itself. It's up to the governing system to connect these events properly.

This gives you a lot of flexibility, since SoundSystem may not originally know about explosions in room, yet you can later connect it, possibly dynamically as needed.

For example, as player moves between rooms, you can unsubscribe player from hearing events that happen in far away rooms.
To be honest, systems like this are often engineered for very large game engines where it is used to decouple dependencies between objects. This isn't an essential system.

struct Message{	long	object_id;	long	type;	int		message;	union	{		int		param;		struct 		{			short	lparam;			short	rparam;		};		void*	data;	};};class IMessageListener{public:	virtual ~IMessageListener(){}	virtual int OnMessage( const Message& message )=0;};class EventManager{private:	typedef std::vector< IMessageListener* > MessageListenerList;	MessageListenerList m_MessageListenerList;public:	EventManager();	~EventManager();	void RegisterMessageListener( IMessageListener* listener );	void UnRegisterMessageListener( IMessageListener* listener );	void SendMessage( long object_id, long type, int message, int param );};
As mentioned above the idea of events is to abstract the actor from the reactor. In our system they're used for that and by the nature of events they are pretty good for multi-threading. In our designs some events do know their target and can send the event "explicitly" to them like file system events (data available), that's they still need to go through some event queue to decouple threads (subsystem vs general purpose threads).

For example in thread N the script triggers an explosion and wants to know all the affected people, the underlying implementation fires an spatial event that the spatial hierarchy listens to and it fires another event when it has managed to process who're in the area.

The bad thing is that the system constantly changes state so if you fire that explosion effect and some object moves out after it was fired but before the spatial system has managed to gather all the objects it's unaffected. Here it's a matter of taste/need, in interactive graphics the changes are usually small enough that humans can't perceive them so it's acceptable.

I can't really give an concrete example since we/I haven't had time to test the system on larger (proper) scale. And on that note if anyone has experience with similar system I'd like to know some feedback too.

E: With our system Input/GUI are just another systems that sends events and subscribe to events (force-feedback, GUI animation).
----There he goes. One of God's own prototypes. Some kind of high powered mutantnever even considered for mass production. Too weird to live, and too rare to die.
In my spare time at work I've been considering such a system but based in Lua (yay tables!).

The basic idea is that 'events' are passed into some kinda controller which then dispatches them to those intrested/named subsystems.

Timed events are handled by simply supplying a time as a parameter and then put into a heap, while the current time > next event in heap dispatch the event; heaps are nicely self organising so I don't invision it being that taxing to work out.

If I get more spare time I might try and knock something up...
Phantom, this was more or less the way I had in mynd for my sistem. Anyway I think it is too early to try to build a system like this. I have got to this conclusion after reading the messages the other pals wrote.

I will leave this for a later time, concentrate now in more shot term taks, and try to see what I really need in the future.


Thanks for all the answers,
HexDump.

This topic is closed to new replies.

Advertisement