Game Development Community

How can I turn this Script into a Behavior?

by Christian Tiago Almeida Marques · in Torque Developer Network · 02/07/2009 (2:00 pm) · 8 replies

Hello. I would like some help on this. I've been trying to turn this script into a behavior, but I'm not able. Can you please help? I've added the behavior header, but it doesn't work. What must i do?

function playerClass::onLevelLoaded(%this, %scenegraph)
{
$player = %this;

moveMap.bindCmd(keyboard, "left", "playerLeft();", "playerLeftStop();");
moveMap.bindCmd(keyboard, "right", "playerRight();", "playerRightStop();");
moveMap.bindCmd(keyboard, "space", "playerJump();", "");
}

function playerLeft()
{
$player.moveLeft = true;
}

function playerLeftStop()
{
$player.moveLeft = false;
}

function playerRight()
{
$player.moveRight = true;
}

function playerRightStop()
{
$player.moveRight = false;
}

function playerJump()
{
if(!$player.airborne)
{
$player.setLinearVelocityY(-200);
$player.airborne = true;
}
}


function playerClass::updateHorizontal(%this)
{
if(%this.moveLeft)
{
%this.setLinearVelocityX(-300);
}

if(%this.moveRight)
{
%this.setLinearVelocityX(300);
}

if(!%this.moveLeft && !%this.moveRight)
{
%this.setLinearVelocityX(0);
}
}

function playerClass::updateVertical(%this)
{
%yVelocity = %this.getLinearVelocityY();

%this.setLinearVelocityY(10);
%collision = %this.castCollision(0.005);

%normalX = getWord(%collision, 4);
%normalY = getWord(%collision, 5);

// no collision
if (%collision $= "")
{
%this.airborne = true;
%this.setConstantForceY(350);
%this.setLinearVelocityY(%yVelocity);
return;
}

// collides with wall to the left
if (%normalX == 1 && %normalY == 0)
{
%this.againstLeftWall = true;
%this.setLinearVelocityX(0);
%this.setLinearVelocityY(%yVelocity);

if(isModifierKey("Space")
{
%this.setLinearVelocityY(-300);
}
return;
}

// collides with wall to the right
if (%normalX == -1 && %normalY == 0)
{
%this.againstRightWall = true;
%this.setLinearVelocityX(0);
%this.setLinearVelocityY(%yVelocity);

if(isModifierKey("Space")
{
%this.setLinearVelocityY(-300);
}

return;
}

// on ground with no wall collisions
if (%normalX == 0 && %normalY == -1)
{
%this.jump=false;
%this.airborne = false;
%this.againstLeftWall = false;
%this.againstRightWall = false;
%this.setConstantForceY(0);
%this.setLinearVelocityY(%yVelocity);
return;
}

// in air and hits platform with head
if (%normalY == 1)
{
%this.airborne = true;
%this.setLinearVelocityX(0);
%this.setConstantForceY(100);
%this.setLinearVelocityY(%yVelocity);
return;
}

// in case another type of collision normal was detected
error("another collison type" SPC %normalX SPC %normalY);
%this.airborne = false;
%this.againstLeftWall = false;
%this.againstRightWall = false;
%this.setLinearVelocityY(%yVelocity);
}

function playerClass::setCurrentAnimation(%this)
{
%xVelocity = %this.getLinearVelocityX();
%yVelocity = %this.getLinearVelocityY();

if (%xVelocity > 0)
{
%this.setFlip(false, false);
}
else if (%xVelocity < 0)
{
%this.setFlip(true, false);
}

if ($player.moveLeft == true || $player.moveRight == true)
{
if (%this.getAnimationName() $= "PlayerAnimation")
{
if(%this.getIsAnimationFinished())
{
%this.playAnimation(PlayerAnimation);
//%this.playAnimation(PlayerAnimation);
return;
}
}else
{
%this.playAnimation(PlayerAnimation);
}
}
else
{
%this.playAnimation(PlayerStand);
}


if (%this.airborne)
{
if(%yVelocity < 0)
{
%this.playAnimation(PlayerJumpUp);
return;
}else
{
%this.playAnimation(PlayerJumpDown);
return;
}
}
}


function PlatformerSceneGraph::onUpdateScene()
{
if (isObject($player))
$player.updateMovement();
}

function playerClass::updateMovement(%this)
{
%this.updateHorizontal();
%this.updateVertical();
%this.setCurrentAnimation();

}

About the author

Recent Threads


#1
02/07/2009 (4:46 pm)
I suggest you get the PSK, it will help you with this and is much more flexible.
#2
02/07/2009 (6:24 pm)
Could you post the entire behavior, header and all? If I can see what you are actually working with, it would make it easier to help out.
#3
02/08/2009 (7:12 am)
Here is the entire behaviour. I tried to create the header, so TGB recognizes the behaviour and the fields, but when I run the game, the player doesn't move, like he isn't assuming the scripts. Thanks in advance for your help.

Because the forum doesn't allow me to post the entire code here, I will just put up a link for it. Thanks.

Please check the class :

http://chrisportfolio.planetaclix.pt/outros/playerClassBehavior.cs
#4
02/09/2009 (9:43 am)
Cool. I'll have a look at it today if you haven't already figured it out.
#5
02/09/2009 (12:12 pm)
I would appreciate it. I only wanted to understand how to turn game scripts and classes into behaviours for easy manipulation. Thanks in advance.
#6
02/09/2009 (10:48 pm)
Here's what I've found:

1. Your onAdd function is incorrect:

Your Code:
function playerClassBehaviour::onBehaviorAddLoaded(%this, %scenegraph)
{...}

Should Be:
function playerClassBehaviour::onBehaviorAdd(%this)
{...}

function playerClassBehaviour::onAddToScene(%this, %scenegraph)
{...}

You want a callback for when the behavior is added to a scene object (onBehaviorAdd) and when the behavior object is added to the scene (onAddToScene). Two different methods.

Next, is the actual content of your onAdd functions. You have assigned the wrong variable to $player

$player = %this;

I'm pretty sure you want to assign $player to the sprite that is using the behavior:

function playerClassBehaviour::onAddToScene(%this, %scenegraph)
{
   $player = %this.owner;
}

Remember that a behavior is just logic attached to a sprite. In these functions, %this refers to the behavior and not the object you wish to manipulate.

Example:
%this.owner.setLinearVelocityX(%whateverValue);

You can use the $player global variable if it is absolutely necessary, but if it is only used in this behavior then you should just use %this.owner.

Another thing I noticed is that you are assigning moveMap controls to stand alone functions, instead of using the behavior's routines:

Your Code:
moveMap.bindCmd(keyboard, "left", "playerLeft();", "playerLeftStop();");

It would be cleaner and make more sense if you used the behavior's functions instead:

My Suggestion:
moveMap.bindObj(keyboard, "left", "playerLeft", %this);

Notice that I am still binding keyboard and the "left" key. What's changed is that I am using bindObj instead of bindCmd. This allows you to bind a key to a function belonging to a class or object, in this case it would be playerClassBehaviour::playerLeft(%this){}
#7
02/09/2009 (10:50 pm)
Read through the above code and start applying some of the changes I suggested, just to get the base behavior ready. Convert the floating script functions into the behavior's methods.

From there you can continue with your actual movement and animation logic. Be sure to post here again to let us know how it worked out, or if you hit another problem.
#8
02/10/2009 (2:50 am)
Thanks Michael. I already made the modifications, but I will only be able to test it later, after work :P

When I try it, you will be informed. Thanks again for your precious help.

Regards,

Chris