Behaviors need events
by Phil Carlisle · in Torque Game Builder · 04/07/2007 (1:19 am) · 12 replies
I think that the behaviors are a great first step towards componentising things. But I think somethings been missed.
Events - yep, I think behaviors need to be able to send and recieve events from within the game.
Example:
You create a "invader" behavior that moves an object from left to right, in small steps. When it hits the right hand side of the screen, you want it to start moving left and vice versa. Now thats fine for a single invader.. works a charm.
Now lets add 100 invaders. Now what happens? Well, either we allow them all to hit the right hand side (not good) or we run through all invaders and tell them to head left when one of the invaders hits the right (again, not so great, although it would work).
My proposal, would be that behaviors should be able to send and recieve event messages. In my scenario:
Invader::onRightWindowHit()
{
sendMessage(%this,"INVADERSMOVELEFTNOW");
}
Would send a message, which would be registered with all invaders... thus:
Invader::onMessage(%message)
{
if(%message $= "INVADERSMOVELEFTNOW") %this.move = leftmovespeed;
}
The reason for using events is that you untie objects, so that one object doesnt need to actually access another. No simset iteration etc..
Events - yep, I think behaviors need to be able to send and recieve events from within the game.
Example:
You create a "invader" behavior that moves an object from left to right, in small steps. When it hits the right hand side of the screen, you want it to start moving left and vice versa. Now thats fine for a single invader.. works a charm.
Now lets add 100 invaders. Now what happens? Well, either we allow them all to hit the right hand side (not good) or we run through all invaders and tell them to head left when one of the invaders hits the right (again, not so great, although it would work).
My proposal, would be that behaviors should be able to send and recieve event messages. In my scenario:
Invader::onRightWindowHit()
{
sendMessage(%this,"INVADERSMOVELEFTNOW");
}
Would send a message, which would be registered with all invaders... thus:
Invader::onMessage(%message)
{
if(%message $= "INVADERSMOVELEFTNOW") %this.move = leftmovespeed;
}
The reason for using events is that you untie objects, so that one object doesnt need to actually access another. No simset iteration etc..
About the author
Recent Threads
#2
Or, if using behaviours, you could put all invaders in one group or set and loop through them to call appropiate functions if a invader hits the left/right border.
Behaviours are a very good and powerful thing but we shouldn't go feature crazy now... just my few cents. :-)
04/07/2007 (4:05 am)
I don't know if this would be already overkill or not... you can easily extent the engine with custom events already. The idea is nice but you could easily work around your example by using a big invisible scene object that all invaders mount to leaving the moving to the control object(for people who don't have the Pro version).Or, if using behaviours, you could put all invaders in one group or set and loop through them to call appropiate functions if a invader hits the left/right border.
Behaviours are a very good and powerful thing but we shouldn't go feature crazy now... just my few cents. :-)
#3
Here is the example excerpt from the header file:
So it would be rather trivial to add EventManager as the behaviour super class or whatever and have access to exactly what you need.
04/07/2007 (6:31 am)
The new TGB beta includes built-in event queues and handler classes (for those who aren't aware of it).Here is the example excerpt from the header file:
$MyEventManager = new EventManager() { queue = "MyEventManager"; };
// Create an event.
$MyEventManager.registerEvent( "SomeCoolEvent" );
// Create a listener and subscribe.
$MyListener = new ScriptMsgListener() { class = MyListener; };
$MyEventManager.subscribe( $MyListener, "SomeCoolEvent" );
function MyListener::onSomeCoolEvent( %this, %data )
{
echo( "onSomeCoolEvent Triggered" );
}
// Trigger the event.
$MyEventManager.postEvent( "SomeCoolEvent", "Data" );So it would be rather trivial to add EventManager as the behaviour super class or whatever and have access to exactly what you need.
#4
Magnus: well, I'm not saying events are any faster code wise, but they are a hell of a lot easier to work with and reduce dependancies from one object to another.
I've worked with both event based and non event based code and the former ALWAYS ends up nicer than the latter. Basically event systems help with creating modular code. Torque is a good example of the opposite :)
I disagree that the code produce is messy, compared to function call code, its a positive NON mess. If supported at the basic object level.
Neo: Yeah, what I'd want is for behaviors to be able to register to recieve events as a native function of the behavior and to recieve them also.
04/07/2007 (8:34 am)
I'm not saying its hard to add event handling, I'm saying it needs it to be native in behaviors for them to really shine (IMHO).Magnus: well, I'm not saying events are any faster code wise, but they are a hell of a lot easier to work with and reduce dependancies from one object to another.
I've worked with both event based and non event based code and the former ALWAYS ends up nicer than the latter. Basically event systems help with creating modular code. Torque is a good example of the opposite :)
I disagree that the code produce is messy, compared to function call code, its a positive NON mess. If supported at the basic object level.
Neo: Yeah, what I'd want is for behaviors to be able to register to recieve events as a native function of the behavior and to recieve them also.
#5
Its not a biggie, I can add this myself, it'd just be good if this was a first class (i.e. a TGB engineered) function rather than my own.
04/07/2007 (8:39 am)
Magnus: the point of my code, was that you want to change the directions of ALL invaders when ONE of them hits the side. Of course you could hack it to read a global direction variable or something horrible like that, but if you want to write nice clean code, I dont think I've come across a better way than using events. with subscribe/publish model. So you DONT loop through all, only subscribed objects (as per Neo's post).Its not a biggie, I can add this myself, it'd just be good if this was a first class (i.e. a TGB engineered) function rather than my own.
#6
Personally I'm just really, really against "events", having been stuck programming windows (MFC) GUIs using events... well... it's a fucking mess. hehe. =)
04/07/2007 (9:05 am)
Phil, I think you missed my point slightly. In the case of the invaders, having a "controller" would be beneficial in a lot of ways. What if you wanted several "groups" of invaders for example? The event driven code would quickly get incredibly messy. With my suggestion it would be a piece of cake just having two (or however many "groups" you needed) controllers. Personally I'm just really, really against "events", having been stuck programming windows (MFC) GUIs using events... well... it's a fucking mess. hehe. =)
#7
I could give you a load of scenarios where events are much cleaner, but it all comes down to one thing, code modularity. Rather than having a lot of objects that inherently must "know" about other objects (thereby introducing dependancies) I'd rather we decoupled them, which is where events come in.
04/07/2007 (2:36 pm)
I've programmed MFC stuff too Magnus, I agree thier implementation isnt great, but event based architectures really ARE more flexible and offer cleaner code.I could give you a load of scenarios where events are much cleaner, but it all comes down to one thing, code modularity. Rather than having a lot of objects that inherently must "know" about other objects (thereby introducing dependancies) I'd rather we decoupled them, which is where events come in.
#8
But not because I hate them, I just think that using EventHandlers is a far cleaner way than bombing all objects with useless events they are not interested in at all.
So out of my sight, what neo posted is a good way of achieving the stuff without starting with decade old event switches which are definitely only there to mess up code.
04/07/2007 (3:03 pm)
I agree on the "con event" postings.But not because I hate them, I just think that using EventHandlers is a far cleaner way than bombing all objects with useless events they are not interested in at all.
So out of my sight, what neo posted is a good way of achieving the stuff without starting with decade old event switches which are definitely only there to mess up code.
#9
04/07/2007 (11:26 pm)
Interesting. I just spent some time a month ago adding the TGE subscription based message handling resource into TGB 1.3 and now it looks like GG did something similar for 1.5. I dont have the beta so I'll wait and see I guess.
#10
I guess either you get it, or you dont. But I'd like to see behaviors move towards the event model, at least supported as a first class part of the interface. If you dont want to use it, dont send any events, but I much much MUCH prefer event based systems for game objects.
So what I'm suggesting wouldnt hurt anyone who didnt want to do it that way, but would help people like me who feel the benefits of that way of working. Either way its not a biggie to make it work, but it would be nice to get it supported in the main codebase.
04/08/2007 (3:20 am)
Marc, I agree that maybe my example wasnt as clean as a listener/subscriber thing, that wasnt the point of the example. What I was trying to show is a use case for why it would be useful to have the functionality.I guess either you get it, or you dont. But I'd like to see behaviors move towards the event model, at least supported as a first class part of the interface. If you dont want to use it, dont send any events, but I much much MUCH prefer event based systems for game objects.
So what I'm suggesting wouldnt hurt anyone who didnt want to do it that way, but would help people like me who feel the benefits of that way of working. Either way its not a biggie to make it work, but it would be nice to get it supported in the main codebase.
#11
But it would need some thoughts on how to implement it because there are ways that does not hurt "non users of it" as well as ways that would have a serious impact on those not using this functionality.
Simplest way: like collision callbacks and the like with a simple on / off state for listening to events.
I most likely would go a step further: Event groups similar to collision groups which would allow you to send events to all objects receiving events or only to a specific event group so you can seperate objects that only rarely get events sent and objects that get them frequently. (example within an rts like game: cpuControlled as an event group for the cpu controlled ones, interactableObjects as an own and most likely the playerControlled as one. don't know if this example makes sense outside my head)
04/09/2007 (11:29 am)
I definitely don't say it would be bad :) I can imagine several scenarios where I myself might have use for it.But it would need some thoughts on how to implement it because there are ways that does not hurt "non users of it" as well as ways that would have a serious impact on those not using this functionality.
Simplest way: like collision callbacks and the like with a simple on / off state for listening to events.
I most likely would go a step further: Event groups similar to collision groups which would allow you to send events to all objects receiving events or only to a specific event group so you can seperate objects that only rarely get events sent and objects that get them frequently. (example within an rts like game: cpuControlled as an event group for the cpu controlled ones, interactableObjects as an own and most likely the playerControlled as one. don't know if this example makes sense outside my head)
#12
The main point of using events, is that you can decouple objects from each other, reducing any code dependancies. Of course you can never truly get rid of dependancies, plus it does add a tiny bit of overhead and makes debugging slightly harder, but its a really flexible way of working.
04/09/2007 (11:50 am)
Well, with the typical publisher/subscriber model, you only get an event if you are subscribed to recieve it.The main point of using events, is that you can decouple objects from each other, reducing any code dependancies. Of course you can never truly get rid of dependancies, plus it does add a tiny bit of overhead and makes debugging slightly harder, but its a really flexible way of working.
Torque Owner Magnus Blikstad
Your scenario is easily accomplished already. Just create an "InvaderController" object and put a parameter in your behavior pointing to it. Something like this;
Invader::onRightWindowHit() { %this.controller.direction = left; } Invader::onUpdate() { if (%this.currentDirection != %this.controller.direction) ---change direction! }