Jump to content
  • Advertisement
Sign in to follow this  
BUnzaga

In game event messaging system.

This topic is 2647 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

I'm working on a new project, and I have thrown around various random ideas and concepts for event driven programming in the past, so I wanted to start this project with one from the ground up, but need some help with the details.

In the past, I usually have used a double array or hash style list, where the 'event type' is the key, and I register objects and call their functions based on the event id.

For example:

function RaiseEvent(id, data){
for(var i in event_list[id]){
event_list[id][id](data);
}
}


That is sort of how it works. So say the id is 'mouseDown', and the data is {x:100, y:100}. It would go to event_list["mouseDown"], which is also an Array / List of objects. These objects all have a 'mouseDown' function, which the 'data' value is passed into.

When an object 'registers' to subscribe to an event, it adds a pointer to itself to the event List...

event_list["mouseDown"][object.id] = object;


This works fine, but I want to see how other engines do it. I want to use it for an internal object to object message event type system, not just for interface stuff, but like... if I get a quest to kill 10 rats, I want to create a listener to check for the 'rat_killed' event, then update the quest info, etc. Or if one object casts a spell, I want to use this messaging system to handle all the game logic in this manner.

I have tried looking up information in google, and reading about how they did it in Dungeon Siege, etc, but I can't seem to get something that I am satisfied with.

Any examples or help is very welcome.

Share this post


Link to post
Share on other sites
Advertisement
I do more or less the same thing you do in my framework and I love it. I'm using ActionScript 3 so I have an easier time with reflection and what not:

I use a message listener map just like you to register callback functions:

public function addMessageListener(messageType : Class, callback : Function) : void
{
if (_messageListenerMap[messageType] == undefined) // only create the list if someone is interested in listening to these messages
_messageListenerMap[messageType] = new Vector.<Function>();

_messageListenerMap[messageType].push(callback);
}

public function removeMessageListener(messageType : Class, callback : Function) : void
{
if (_messageListenerMap[messageType] != undefined)
{
var index : int = _messageListenerMap[messageType].indexOf(callback);

if(index != -1)
_messageListenerMap[messageType].splice(index, 1);
}
}


I post Message objects that contain all of the relevant data in a nice type safe way (I pass the type with the Message because AS3 doesn't have a super quick way of getting the object type):


public function postMessage(message : Message, messageType : Class) : void
{
if (_messageListenerMap[messageType] != undefined)
{
var callbacks : Vector.<Function> = _messageListenerMap[messageType];

var count : int = callbacks.length;

for (var i : int = 0; i < count; ++i)
callbacks(message);
}
}


It's working great!

The only thing I would say that a RatKilledMessage is probably a little overkill. I'd make an EntityKilledMessage and mark a "type" member as 'rat' and let the quest that's listening do a check like:


if(entityKilledMessage.type == "rat")
{
++ratsKilled;

if(ratsKilled > 10)
world.postMessage(new QuestCompleteMessage(this), QuestCompleteMessage);
}


I think you're on a great track -- only entities interested in specific messages receive them instead of shooting every message to every object.

Share this post


Link to post
Share on other sites
Nice, it looks like both of our systems are almost identical. I use Javascript in the engine I use (DX Studio). Here is my actual script, if you, or anyone else wants to take a look at it. I don't use comments much, that is something I intend to work on.



var eQueue = []; // array queue of events
var eList = {}; // 'lsit' of events

function HandleQueue(){
var next;
while (next=eQueue.shift()){
for(var i in eList[next.event.id]){
eList[next.event.id](next.data);
}
}
}

function RaiseEvent(_e, _data){
eQueue.push({event:_e, data:_data});
}

function RegisterListener(_e, _id, _func){
if(null == eList[_e]){
eList[_e] = {};
}
eList[_e][_id] = _func;
}

function UnregisterListener(_e, _id){
if(null == eList[_e]){return;}
delete eList[_e][_id];
if(eList[_e].__count__ <= 0){
delete eList[_e];
}
}


I added an additional step of an 'event queue'. I am just testing this out for now, but it looks promising. I basically just call the HandleQueue function onUpdate. I adapted your 'pass the function' system you posted, I like that. :)

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!