Adding behaviors from code
by Jason McIntosh · in Torque Game Builder · 08/03/2007 (4:53 pm) · 14 replies
I'm doing this:
I have a function Unit::onClick() but it never gets called when I click on the sprite.
What am I doing wrong?
%onClick = new BehaviorInstance()
{
template=GenericButtonBehavior;
};
%obj.addBehavior( %onClick );%obj (a t2dStaticSprite with the class set to "Unit") is set to use mouse events and is in the scene.I have a function Unit::onClick() but it never gets called when I click on the sprite.
What am I doing wrong?
About the author
#2
08/03/2007 (9:04 pm)
There are some intricacies to creating a behavior, and the template knows how to do it all. Among other things, it's got to set up the behavior's fields properly.
#3
It looks like if you use the keyword _behaviorX = "SomeBehaviorTemplate"
Where is X is an incrementing behavior count it will work.
08/16/2007 (3:57 am)
I took a peek at the code generated when you add behaviors via the editor.new t2dStaticSprite() {
imageMap = "heart_smashshop2ImageMap";
frame = "0";
canSaveDynamicFields = "1";
config = "SmashItemDatablock";
useMouseEvents = "1";
Position = "-27.468 16.213";
size = "15.063 15.063";
Damage = "Adds 5% Health";
Desc = "Health +5%";
mountID = "10";
Price = "125";
_behavior0 = "MouseOverGrowBehavior";
_behavior1 = "MouseOverSoundBehavior";
_behavior2 = "MouseDownSoundBehavior";
};It looks like if you use the keyword _behaviorX = "SomeBehaviorTemplate"
Where is X is an incrementing behavior count it will work.
#4
I'm interested how to set up these fields properly while adding behavior from code
I'm using the _behavior0 = "MouseOverGrowBehavior"; idea- it almost works but lacks the fields to run fully.
e.g the MouseOverGrowBehavior needs 2 addbehavior fields :- scaletime & scalefactor if it is the one that comes with tgb 1.51
how would you code these fields?
08/31/2007 (6:27 am)
From spider :- "it's got to set up the behavior's fields properly."I'm interested how to set up these fields properly while adding behavior from code
I'm using the _behavior0 = "MouseOverGrowBehavior"; idea- it almost works but lacks the fields to run fully.
e.g the MouseOverGrowBehavior needs 2 addbehavior fields :- scaletime & scalefactor if it is the one that comes with tgb 1.51
how would you code these fields?
#5
Any suggestions on improving this method, fire away :) There are obviously some things to consider when doing this like Spider said. Such as what the behaviours set up themselves and what you must set yourself among other things.
Also, doing it the other way with the _behaviour array (looks like an array but not checked tho) I'd guess you'd have to set the properties properly like the editor does. They look tab delimited as well so you are probably better off using the above method if your editors tabs are spaces like mine :)
Setting them this way would probably look something like this:
08/31/2007 (8:18 am)
@John - Hi - I have a behaviour that kinda does what you are thinking. This is a shortened version of a chase behaviour being dynamically attached to a trigger when certain conditions are met. The code shown is the bit that actually attaches the behaviour, sets it up, and activates it as that's what we're interested in here.//create an instance of the behaviour
%followAndThrust = FollowAndThrustBehavior.createInstance();
// set its fields ...
%followAndThrust.useConstant = false;
%followAndThrust.turnSpeed = 0.0;
%followAndThrust.rotationOffset = 0.0;
// we want to keep its defaults so ... we attach it to the owner. and then get it back and kick it into action.
// ARG!!! this is clunky but seems to work fine :)
%this.owner.addBehavior(%followAndThrust);
%followAndThrust = %this.owner.getBehavior("FollowAndThrustBehavior");
%followAndThrust.onAddToScene();Any suggestions on improving this method, fire away :) There are obviously some things to consider when doing this like Spider said. Such as what the behaviours set up themselves and what you must set yourself among other things.
Also, doing it the other way with the _behaviour array (looks like an array but not checked tho) I'd guess you'd have to set the properties properly like the editor does. They look tab delimited as well so you are probably better off using the above method if your editors tabs are spaces like mine :)
Setting them this way would probably look something like this:
_behavior6 = "CountOnDeathBehavior count 500 counter Player";The spaces between the settings were tabs so cutting and pasting that from here is unlikely to work.
#6
Method 1:
Method 2:
If you want to change behaviors on the fly, it can also be useful to store a reference to the behavior object in your object. To use Saiko's example again, you could add this line:
08/31/2007 (10:14 am)
There are two separate things being talked about here.Method 1:
_behavior6 = "CountOnDeathBehavior count 500 counter Player";is how a behavior is stored when it's serialized into a level file. That is, when you save a level from the editor. I'm not sure how you would use this to add behaviors during execution, but if you wanted to paste a bunch of behaviors directly into your level file, this is how you would do it.
Method 2:
%followAndThrust = FollowAndThrustBehavior.createInstance();
%this.owner.addBehavior(%followAndThrust);
%followAndThrust = %this.owner.getBehavior("FollowAndThrustBehavior");
%followAndThrust.onAddToScene();This is how you add a behavior in code. Setting fields is very simple using this method, and it is just as described by Saiko... you just set the fields (same names as in the editor... no 'friendly naming' here.)%followAndThrust.useConstant = false; %followAndThrust.turnSpeed = 0.0;
If you want to change behaviors on the fly, it can also be useful to store a reference to the behavior object in your object. To use Saiko's example again, you could add this line:
%this.followAndThrust = %followAndThrust;This saves you having to do the getBehavior call every time you want to change a behavior field. Also, if you have 2 instances of a behavior, getBehavior will only ever return the first one so unless you want to loop through all the objects behaviors (which is possible using getBehaviorCount and getBehaviorByIndex) it is definitely worthwhile to store your instances.
#7
thanx both
I'm now working at coding behaviors using method 2
Because I'm new to coding with torque I would be very grateful if I could see the above/ or similar code in full detail showing function calls etc- where to put behavior definition and functions and how to link behavior to objects
Has anyone got a code sample to show me?
Thanx in advance of replies
09/01/2007 (2:27 am)
The reason I was looking at method 1 - I have objects on my level at the start which I can use the editor to set the behavior - while I also have objects created during the running of the level which need same or very similar behavior pattern - i was hoping to put it into the "new t2dAnimatedSprite" definitionthanx both
I'm now working at coding behaviors using method 2
Because I'm new to coding with torque I would be very grateful if I could see the above/ or similar code in full detail showing function calls etc- where to put behavior definition and functions and how to link behavior to objects
Has anyone got a code sample to show me?
Thanx in advance of replies
#8
Also you can look at all the behaviors in the behaviorplayground or TDN for reference.
Look in here (or whatever your install directory is and look for behaviorplayground):
C:\Program Files\GarageGames\TorqueGameBuilder-1.5.1\games\BehaviorPlayground\game\behaviors
09/03/2007 (8:48 pm)
Basic creation and use of behaviors is covered in the 1.5.1 documentation.Also you can look at all the behaviors in the behaviorplayground or TDN for reference.
Look in here (or whatever your install directory is and look for behaviorplayground):
C:\Program Files\GarageGames\TorqueGameBuilder-1.5.1\games\BehaviorPlayground\game\behaviors
#9
I am interested in how to fully code it without the editor and on the 'fly'.
09/04/2007 (11:08 am)
These reference explain how to do behaviors within the editorI am interested in how to fully code it without the editor and on the 'fly'.
#10
As for adding behaviors to objects from script:
%obj.addbehavior(behaviortemplatename.getinstance());
Look at the TGB Reference > BehaviorTemplate and BehaviorInstance to see all methods available.
09/04/2007 (11:51 am)
The creation of a behavior script is covered in the documentation, its the fish demo under the behavior tutorial section. As for adding behaviors to objects from script:
%obj.addbehavior(behaviortemplatename.getinstance());
Look at the TGB Reference > BehaviorTemplate and BehaviorInstance to see all methods available.
#11
In general, as a recap...
1) write a behavior. See the fish demo, or just look at any of the behavior files in the behavior playground.
2) use the method in James' (or my) post to add the behavior to an object 'on the fly'
That's about it.
09/04/2007 (1:19 pm)
@John: I think we are all talking about coding behaviors without the editor. What is your question specifically?In general, as a recap...
1) write a behavior. See the fish demo, or just look at any of the behavior files in the behavior playground.
2) use the method in James' (or my) post to add the behavior to an object 'on the fly'
That's about it.
#12
I now understand how to do it
thanx all
09/06/2007 (11:09 am)
@ spider et al sorry 4 my confusion - your in general/recap is what I needed !I now understand how to do it
thanx all
#13
I have an object named "ship" of the class Turret and I try to call the function. This is the output from the console:
Sorry if I don't understand this correctly, but why in the example are you using %this.owner.addBehavior to attach the behavior? I thought only behaviors had owners, and that's only after they've been added.
I tried to take out the owner part and it still doesn't work. But it complains less.
10/13/2007 (9:10 pm)
I'm having trouble getting this to work properly. Here's my code:function Turret::targetBehavior(%this, %class, %turnSpeed, %rotationOffset)
{
// create an instance of the behavior
%faceNearestClass = FaceNearestClassBehavior.createInstance();
// set its fields
%faceNearestClass.classType = %class;
%faceNearestClass.turnSpeed = %turnSpeed;
%faceNearestClass.rotationOffset = %rotationOffset;
// attach it to the owner
%this.owner.addbehavior(%faceNearestClass);
%faceNearestClass = %this.owner.getBehavior("FaceNearestClassBehavior");
%faceNearestClass.onAddToScene();
// make a reference to this behavior so we can change it later
%this.faceNearestClass = %faceNearestClass;
}I have an object named "ship" of the class Turret and I try to call the function. This is the output from the console:
==>ship.targetBehavior(mob, 270, 0); game/gameScripts/turret.cs (10): Unable to find object: '' attempting to call function 'addBehavior' game/gameScripts/turret.cs (11): Unable to find object: '' attempting to call function 'getBehavior' game/gameScripts/turret.cs (12): Unable to find object: '0' attempting to call function 'onAddToScene' ==>ship.targetBehavior(%this, mob, 270, 0); game/gameScripts/turret.cs (10): Unable to find object: '' attempting to call function 'addBehavior' game/gameScripts/turret.cs (11): Unable to find object: '' attempting to call function 'getBehavior' game/gameScripts/turret.cs (12): Unable to find object: '270' attempting to call function 'onAddToScene' ==>ship.targetBehavior(%this, "mob", 270, 0); game/gameScripts/turret.cs (10): Unable to find object: '' attempting to call function 'addBehavior' game/gameScripts/turret.cs (11): Unable to find object: '' attempting to call function 'getBehavior' game/gameScripts/turret.cs (12): Unable to find object: '270' attempting to call function 'onAddToScene'
Sorry if I don't understand this correctly, but why in the example are you using %this.owner.addBehavior to attach the behavior? I thought only behaviors had owners, and that's only after they've been added.
I tried to take out the owner part and it still doesn't work. But it complains less.
#14
Also, I didn't understand the proper way to call the function. It works when I do ship.targetBehavior(mob, 270, 0);
Another thing is that while I was copying the general layout of other behaviors, I found that I don't have an onAddToScene function, but instead I have a onBehaviorAdd function. So I changed the above example to use that function.
I'm not sure if this is necessary, but I used a separate function to change the behavior parameters so it wouldn't keep creating a new behavior each time:
EDIT: I wasn't clearing the SimSet so it was keeping old values for targets. I fixed that and have updated my post to reflect that everything is working properly.
10/13/2007 (9:30 pm)
Okay so I figured it out. It worked when I removed the %this.owner.addBehavior and just did %this.addBehavior.Also, I didn't understand the proper way to call the function. It works when I do ship.targetBehavior(mob, 270, 0);
Another thing is that while I was copying the general layout of other behaviors, I found that I don't have an onAddToScene function, but instead I have a onBehaviorAdd function. So I changed the above example to use that function.
I'm not sure if this is necessary, but I used a separate function to change the behavior parameters so it wouldn't keep creating a new behavior each time:
function Turret::changeTargetBehavior(%this, %class, %turnSpeed, %rotationOffset)
{
%this.faceNearestClass.classType = %class;
%this.faceNearestClass.turnSpeed = %turnSpeed;
%this.faceNearestClass.rotationOffset = %rotationOffset;
}EDIT: I wasn't clearing the SimSet so it was keeping old values for targets. I fixed that and have updated my post to reflect that everything is working properly.
Torque Owner Jason McIntosh
Dunno why this works and the other way doesn't.