Trying to add a behavior through script...
by Orion the Hunter · in Torque Game Builder · 12/06/2012 (9:52 am) · 24 replies
Alright. So I got this cool behavior that scales an object. What I want to do is make it so that when my snake dies, he starts growing bigger and then he kills everyone. Here is what I have so far:
Unfortunately, the console is giving me errors towards the _behavior2 part. It's a syntax error so it should be fairly easy to fix but i don't see anything wrong with it.
Thanks!
function SnakeClass::onDeath( %this, %dAmount, %srcObject )
{
_behavior2 = "ScaleBehavior\txWidthMin\t20\tyWidthMin\t20\txWidthMax\t30\tyWidthMax\t30\tGrow";
%this.DisableGravity = false;
if ( isObject( %this.DrillHead ) )
{
%this.DrillHead.safeDelete();
}
}Unfortunately, the console is giving me errors towards the _behavior2 part. It's a syntax error so it should be fairly easy to fix but i don't see anything wrong with it.
Thanks!
#2
12/07/2012 (6:42 am)
Thanks! The only problem is, it scales from the default settings and it scales in the kill animations. Maybe if I set the defaults to the size I want for my snake, then it will work? Also, I'll just have a image map where it's just standing there and link that to an explosion. I'll sync it in time with the scale. I'll let you know the results...
#3
12/07/2012 (9:11 am)
Huh. Torque didn't like that idea. Apparently, the scale behavior is still not being added, even with your code... do I need to add more parameters or something? Just so you know, an AI controller behavior is already added to the snake by default. We do not want to override that behavior.
#4
I genuinely appreciate the humor in the personification of Torque, but you need to supply us with errors if the community is to help you. I know it takes time, but it is definitely a net gain for everyone if you include error descriptions every time you say something didn't work.
12/07/2012 (11:36 am)
There's a way to programmtically change the behavior that you add to a sprite. I don't know off the top of my head, but it shouldn't be too bad. Changing defaults to accommodate one case is a patently bad idea.I genuinely appreciate the humor in the personification of Torque, but you need to supply us with errors if the community is to help you. I know it takes time, but it is definitely a net gain for everyone if you include error descriptions every time you say something didn't work.
#5
Anyway, if the console was giving me errors I'd definitely feed 'em through. The only result I get is the snake not scaling, even when I tried the script Mr. Ranft gave me.
12/07/2012 (3:26 pm)
Well that's just the thing: There are no errors. BTW, I found you were right about accommodating one little thing like that. It messed up all my other behaviors so I just switched it back.Anyway, if the console was giving me errors I'd definitely feed 'em through. The only result I get is the snake not scaling, even when I tried the script Mr. Ranft gave me.
#6
Perhaps drop that behavior code in here so we can help out a little....
And hold the phone a second.
perhaps try something more like this:
Just noticed in the docs that addBehavior() takes a behavior instance as a parameter, not a behavior template.
12/07/2012 (5:35 pm)
Did you add an onBehaviorAdd() method to your scale behavior and in that method call the method to begin the behavior?Perhaps drop that behavior code in here so we can help out a little....
And hold the phone a second.
perhaps try something more like this:
%instance = ScaleBehavior.createInstance(); // now we can set values on the behavior instance %instance.myScaleValue = 2.5; %object.addBehavior(%instance);
Just noticed in the docs that addBehavior() takes a behavior instance as a parameter, not a behavior template.
#7
12/07/2012 (8:23 pm)
Here is the Scale Behavior script://-----------------------------------------------------------------------------
// Torque Game Builder - Scale Effect behaviour
// Version: 1.0
// mike@saikosystems.co.uk (Saiko)
//-----------------------------------------------------------------------------
if (!isObject(ScaleBehavior))
{
%template = new BehaviorTemplate(ScaleBehavior);
%template.friendlyName = "Scale Effect";
%template.behaviorType = "Effects";
%template.description = "Scale the object an object over time";
//Customization Options
%template.addBehaviorField(xWidthMin, "Minimum x width", float, 5.0);
%template.addBehaviorField(yWidthMin, "Minimum y width", float, 5.0);
%template.addBehaviorField(xWidthMax, "Maximum x width", float, 25.0);
%template.addBehaviorField(yWidthMax, "Maximum y width", float, 25.0);
%template.addBehaviorField(Time, "The time (in seconds) to scale", float, 2.0);
%template.addBehaviorField(DelayStart, "The time (in seconds) to delay scale starting", float, 0);
%template.addBehaviorField(Increment, "Set the number of increments per second (0 defaults 31 steps per second)", int, 0);
%template.addBehaviorField(Pulse, "Continously scale up and down (Pulse)", bool, false);
%template.addBehaviorField(Grow, "Should object grow from original size to maximum? (Grow)", bool, false);
%template.addBehaviorField(AutoRotate, "Rotate", float, 0);
%template.addBehaviorField(DeleteObject, "Delete the object when scale is finished", bool, false);
}
function ScaleBehavior::onBehaviorAdd(%this)
{
%this.startSize = %this.xWidthMin SPC %this.yWidthMin;
%this.endSize = %this.xWidthMax SPC %this.yWidthMax;
if(%this.Increment == 0)
{
%this.stepIncrement = 31;
}
else
{
%this.stepIncrement = %this.Increment;
}
%this.xStepIncrement = (%this.xWidthMax - %this.xWidthMin) / (%this.Time * %this.stepIncrement);
%this.yStepIncrement = (%this.yWidthMax - %this.yWidthMin) / (%this.Time * %this.stepIncrement);
%this.direction = false;
if (%this.AutoRotate != 0)
{
%this.owner.setAngularVelocity(%this.AutoRotate);
}
if (%this.DelayStart > 0)
{
%this.schedule(%this.DelayStart * 1000, "startScale");
}
else
{
%this.startScale();
}
}
function ScaleBehavior::startScale(%this)
{
if (%this.Grow)
{
%this.owner.size = %this.startSize;
%this.direction = true;
}
else
{
%this.owner.size = %this.endSize;
%this.direction = false;
}
// enable our update callaback
%this.owner.enableUpdateCallback();
}
function ScaleBehavior::endScale(%this)
{
if(%this.Pulse)
{
// swap direction
if (%this.direction)
{
%this.direction = false;
}
else
{
%this.direction = true;
}
}
else
{
// if we are not pulsing we drop the update callback
%this.owner.disableUpdateCallback();
if(%this.DeleteObject)
{
%this.owner.safeDelete();
}
}
}
function ScaleBehavior::onUpdate(%this)
{
if(%this.direction)
{
%newX = %this.owner.size.x + %this.xStepIncrement;
%newY = %this.owner.size.y + %this.yStepIncrement;
%this.owner.size = %newX SPC %newY;
if((%this.owner.size.x > %this.xWidthMax) || (%this.owner.size.y > %this.yWidthMax))
{
%this.owner.size = %this.endSize;
%this.endScale();
}
}
else
{
%newX = %this.owner.size.x - %this.xStepIncrement;
%newY = %this.owner.size.y - %this.yStepIncrement;
%this.owner.size = %newX SPC %newY;
if((%this.owner.size.x < %this.xWidthMin) || (%this.owner.size.y < %this.yWidthMin))
{
%this.owner.size = %this.startSize;
%this.endScale();
}
}
}
#8
To use your function:
12/07/2012 (11:13 pm)
Ok, I've just tried it and it works fine:%instance = ScaleBehavior.createInstance(); // added because the defaults made it shrink before I could catch it.... %instance.pulse = true; %object.addBehavior(%instance);You can set your fields as I have done before adding the behavior instance to the object to get it to act as you wish.
To use your function:
function SnakeClass::onDeath( %this, %dAmount, %srcObject )
{
%instance = ScaleBehavior.createInstance();
%this.addBehavior(%instance);
%this.DisableGravity = false;
if ( isObject( %this.DrillHead ) )
{
%this.DrillHead.safeDelete();
}
}
#9
12/08/2012 (5:51 am)
Okay, cool. So where should I put your first code? Quote:Ok, I've just tried it and it works fine:
view plaincopy to clipboardprint?
%instance = ScaleBehavior.createInstance();
// added because the defaults made it shrink before I could catch it....
%instance.pulse = true;
%object.addBehavior(%instance);
#10
The actual code I used (which would not work correctly in a game because you don't want this to happen until a SnakeClass object "dies") was in common/gameScripts/levelManagement.cs:
So immediately on level load the behavior instance is created, modified and then added to the sprite object (assuming the object is named correctly).
I also enabled mouse events on that sprite and then moved that code to the MySprite::onMouseDown() handler. The sprite sat there patiently until I clicked it, whereupon it proceeded to scale using its newly added behavior.
As you see, I tried it with pulse on and with just the defaults.
So, as in my last post, your SnakeClass' onDeath method should contain the code to create the behavior instance and add it to itself:
12/08/2012 (7:46 am)
That first snip would go anywhere you might want to add the behavior to an object. Just like I illustrated inside of the SnakeClass::onDeath() function in my second code snip.The actual code I used (which would not work correctly in a game because you don't want this to happen until a SnakeClass object "dies") was in common/gameScripts/levelManagement.cs:
function t2dSceneObject::onLevelLoaded(%this, %scenegraph)
{
if (%this.getName() $= "MySprite")
{
%instance = ScaleBehavior.createInstance();
// added because the defaults made it shrink before I could catch it....
%instance.pulse = true;
%this.addBehavior(%instance);
}
}So immediately on level load the behavior instance is created, modified and then added to the sprite object (assuming the object is named correctly).
I also enabled mouse events on that sprite and then moved that code to the MySprite::onMouseDown() handler. The sprite sat there patiently until I clicked it, whereupon it proceeded to scale using its newly added behavior.
function MySprite::onMouseDown(%this)
{
%instance = ScaleBehavior.createInstance();
//%instance.pulse = true;
%this.addBehavior(%instance);
}As you see, I tried it with pulse on and with just the defaults.
So, as in my last post, your SnakeClass' onDeath method should contain the code to create the behavior instance and add it to itself:
function SnakeClass::onDeath( %this, %dAmount, %srcObject )
{
// -----------------------------------------
// This part right here
%instance = ScaleBehavior.createInstance();
%this.addBehavior(%instance);
// -----------------------------------------
%this.DisableGravity = false;
if ( isObject( %this.DrillHead ) )
{
%this.DrillHead.safeDelete();
}
}
#11
And then in LevelManagement.cs,
Did I do the placement the wrong way? Needless to say it doesn't work and the console gives no errors.
12/08/2012 (2:25 pm)
Hmm. Still no results... So I added this to SnakeMethods.cs:function SnakeClass::onDeath( %this, %dAmount, %srcObject )
{
// -----------------------------------------
// This part right here
%instance = ScaleBehavior.createInstance();
%this.addBehavior(%instance);
// -----------------------------------------
%this.DisableGravity = false;
if ( isObject( %this.DrillHead ) )
{
%this.DrillHead.safeDelete();
}
}And then in LevelManagement.cs,
function t2dSceneObject::onLevelLoaded(%this, %scenegraph)
{
if (%this.getName() $= "SnakeDieAnimation")
{
%instance = ScaleBehavior.createInstance();
// added because the defaults made it shrink before I could catch it....
%instance.pulse = true;
%this.addBehavior(%instance);
}
}Did I do the placement the wrong way? Needless to say it doesn't work and the console gives no errors.
#12
What type of object is "SnakeDieAnimation?" In levelManagement.cs, throw an echo in to see if it's even hitting that code:
12/08/2012 (3:39 pm)
"Needless to say?" Hardly. I cut and pasted your behavior, tacked those two different methods of adding the behavior into place in a matter of minutes and it worked fine. The console shows no errors because there are none.What type of object is "SnakeDieAnimation?" In levelManagement.cs, throw an echo in to see if it's even hitting that code:
function t2dSceneObject::onLevelLoaded(%this, %scenegraph)
{
if (%this.getName() $= "SnakeDieAnimation")
{
echo(" @@@ t2dSceneObject::onLevelLoaded() called");
%instance = ScaleBehavior.createInstance();
// added because the defaults made it shrink before I could catch it....
%instance.pulse = true;
echo(" @@@ behavior instance ID: " @ %instance);
%this.addBehavior(%instance);
}
}Throw similar echo() statements into your onDeath() method.
#13
I did what you said but got no echos...
12/09/2012 (8:27 am)
I meant needless to say in the sense that obviously it doesnt work or I wouldn't be having problems. ;)I did what you said but got no echos...
#14
If the t2dSceneObject::onLevelLoaded() method isn't being called, then it seems that you're working with an object that does not exist at level load time. Try moving that code to
Just add this function right below the ::onLevelLoaded() function and see what it does.
12/09/2012 (10:58 am)
Ok, progress - if you get no console output from an echo in your "onDeath" method then it isn't working because the onDeath method isn't being called.If the t2dSceneObject::onLevelLoaded() method isn't being called, then it seems that you're working with an object that does not exist at level load time. Try moving that code to
function t2dSceneObject::onAdd(%this)
{
if (%this.getName() $= "SnakeDieAnimation")
{
echo(" @@@ t2dSceneObject::onLevelLoaded() called");
%instance = ScaleBehavior.createInstance();
// added because the defaults made it shrink before I could catch it....
%instance.pulse = true;
echo(" @@@ behavior instance ID: " @ %instance);
%this.addBehavior(%instance);
}
}Just add this function right below the ::onLevelLoaded() function and see what it does.
#15
12/09/2012 (11:13 am)
Still nothing... Hmm...
#16
Try changing that onAdd() to this:
Maybe this way we can see the names of all scene objects added to the scene and can find out why your object's onAdd() and onDeath() are not being called.
12/09/2012 (5:38 pm)
Wait - what is the name of the sprite you're adding the behavior to?Try changing that onAdd() to this:
function t2dSceneObject::onAdd(%this)
{
echo(" @@@ t2dSceneObject::onLevelLoaded() called: " @ %this @ " : " @ %this.getName());
if (%this.getName() $= "SnakeDieAnimation")
{
echo(" @@@ t2dSceneObject::onLevelLoaded() called");
%instance = ScaleBehavior.createInstance();
// added because the defaults made it shrink before I could catch it....
%instance.pulse = true;
echo(" @@@ behavior instance ID: " @ %instance);
%this.addBehavior(%instance);
}
}Maybe this way we can see the names of all scene objects added to the scene and can find out why your object's onAdd() and onDeath() are not being called.
#17
12/09/2012 (7:30 pm)
Sorry—this will sound very noobish. The sprite is like "SnakeDieAnimation" and "SnakeImageMap" right?
#18
12/09/2012 (8:14 pm)
...I'm still not getting any echoes.
#19
If you're not getting any echos at all then what is in your level? As the level loads the latest version of onAdd() there should echo out the object ID and name (if it has one) of every scene object that is in the level as it is added to the scene.
12/09/2012 (9:42 pm)
Nope - those sound more like an animation datablock and an image datablock. The sprite is a t2dAnimatedSprite or t2dStaticSprite object in your level. Both of these object types are derived from t2dSceneObject, so the callbacks on that class should affect them as well.If you're not getting any echos at all then what is in your level? As the level loads the latest version of onAdd() there should echo out the object ID and name (if it has one) of every scene object that is in the level as it is added to the scene.
#20
Is that what you're talking about?
12/10/2012 (6:13 am)
Well I see about five billion errors like this: Object (4544) SnakeClass -> pskActor2D -> pskActor -> t2dSceneObject -> BehaviorComponent -> DynamicConsoleMethodComponent -> SimComponent -> SimObjectIs that what you're talking about?
Torque Owner Richard Ranft
Roostertail Games
function SnakeClass::onDeath( %this, %dAmount, %srcObject ) { %this.addBehavior(ScaleBehavior); %this.DisableGravity = false; if ( isObject( %this.DrillHead ) ) { %this.DrillHead.safeDelete(); } }Also, you can ensure that the scale behavior fires off by setting up its onBehaviorAdd() method so that it starts its scaling (or whatever) when it's added.
Just setting that _behavior2 field does not correctly add the behavior to the object (and there is no internal setter function attached to those fields so this won't work anyway).
Remember to follow the inheritance chain when looking for how to handle objects - t2dSceneObjects inherit from BehaviorComponent, which has the addBehavior() method that you need to call to add a behavior to a scene object at runtime.
Hope that helps!