TGB/Tutorials/FishGameBehavior
From TDN
[edit] IntroductionThis is an extremely high level tutorial. Before you start, make sure you have learned basic TorqueScript syntax, TGB Editor Basics, and behavior concepts. If you are completely new to Torque, specifically TGB, I recommended you go through the other tutorials found in this documentation first.
[edit] Making Our Fish MoveIn this section we are introduced to behaviors in the process of creating a movement behavior. We set this movement behavior up to take key input to allow us to configure our movement keys inside the Level Builder itself. First you want to create a new project. If you are unsure how to do this, click here. I named mine "MyFishTutorial".
For our fish game we need only three behaviors. Behaviors are sets of scripts we can create and then assign to various object inside the Level Builder. Not only can we assign them but we can configure different values to customize the behavior. We will need to create three different behaviors for this quick and simple game, as follows:
if(!isObject(fishControlsBehavior))
{
%template = new BehaviorTemplate(fishControlsBehavior);
%template.friendlyName = "Fish Tutorial Controls";
%template.behaviorType = "Input";
%template.description = "Movement control for our Fish Tutorial";
%template.addBehaviorField(upKey, "Key to bind to upward movement", keybind, "Up");
%template.addBehaviorField(downKey, "Key to bind to downward movement", keybind, "Down");
%template.addBehaviorField(leftKey, "Key to bind to left movement", keybind, "Left");
%template.addBehaviorField(rightKey, "Key to bind to right movement", keybind, "Right");
%template.addBehaviorField(verticalSpeed, "Speed when moving vertically", float, 15.0);
%template.addBehaviorField(horizontalSpeed, "Speed when moving horizontally", float, 30.0);
}
function fishControlsBehavior::onBehaviorAdd(%this)
{
if (!isObject(moveMap))
return;
// bind our keys on the keyboard
moveMap.bindObj(getWord(%this.upKey, 0), getWord(%this.upKey, 1), "moveUp", %this);
moveMap.bindObj(getWord(%this.downKey, 0), getWord(%this.downKey, 1), "moveDown", %this);
moveMap.bindObj(getWord(%this.leftKey, 0), getWord(%this.leftKey, 1), "moveLeft", %this);
moveMap.bindObj(getWord(%this.rightKey, 0), getWord(%this.rightKey, 1), "moveRight", %this);
%this.up = 0; %this.down = 0; %this.left = 0; %this.right = 0;
}
function fishControlsBehavior::moveUp(%this, %val)
{
%this.up = %val;
%this.updateMovement();
}
function fishControlsBehavior::moveDown(%this, %val)
{
%this.down = %val;
%this.updateMovement();
}
function fishControlsBehavior::moveLeft(%this, %val)
{
%this.left = %val;
%this.updateMovement();
}
function fishControlsBehavior::moveRight(%this, %val)
{
%this.right = %val;
%this.updateMovement();
}
function fishControlsBehavior::updateMovement(%this)
{
// figure out what speed in what direction we are moving based on key input
%this.owner.setLinearVelocityX((%this.right - %this.left) * %this.horizontalSpeed);
%this.owner.setLinearVelocityY((%this.down - %this.up) * %this.verticalSpeed);
// check whether or not we need to flip our direction
if((%this.left != %this.right) && (%this.left != %this.owner.getFlipX()))
%this.owner.setFlipX(%this.left);
}
The behavior you just created adds the ability to control the object it is attached to. You will be able to choose which keys move the object up, down, left, and right. It even allows you to add default values for the behavior fields. Time to try it out. Re-open TGB and load up your project again.
[edit] Giving Our Fish Health
We are going to add some more behaviors that we want to show up in the Level Builder, so close down TGB. Create a script file called "fishHealthManagement.cs" inside your Project Directory/game/behaviors folder, using the following code:
if(!isObject(fishHealthManagementBehavior))
{
%template = new BehaviorTemplate(fishHealthManagementBehavior);
%template.friendlyName = "Fish Tutorial Health Management";
%template.behaviorType = "Gameplay";
%template.description = "Health management for our Fish Tutorial";
%template.addBehaviorField(health, "The current health of the fish", float, 100);
%template.addBehaviorField(maxHealth, "The max health of the fish", float, 100);
%template.addBehaviorField(healthLossTime, "The ammount of seconds the fish should lose health", float, 3.00);
%template.addBehaviorField(healthLossValue, "The ammount of health the fish loses over time", float, -10);
}
function fishHealthManagementBehavior::onBehaviorAdd(%this)
{
// calculate the min health
%this.minHealth = %this.maxHealth * 0.20;
// set the max width and height to the starting width and height
%this.maxWidth = %this.owner.getWidth();
%this.maxHeight = %this.owner.getHeight();
// if we are to take damage we must receive collision
%this.owner.setCollisionActive(false, true);
// set a flag to signify that we have health
%this.owner.hasHealth = true;
%this.owner.enableUpdateCallback();
%this.lastSceneTime = 0;
}
function fishHealthManagementBehavior::updateHealth(%this, %modifier)
{
// modify our health based on the modifier
%this.health += %modifier;
// lets clamp the values between the min health and the max health
if(%this.health > %this.maxHealth)
{
%this.health = %this.maxHealth;
}
else if(%this.health < %this.minHealth)
{
%this.health = %this.minHealth;
}
// call the update size method
%this.updateSize();
}
function fishHealthManagementBehavior::updateSize(%this)
{
// get a multiplier based on current health out of max health
%healthMultiplier = %this.health / %this.maxHealth;
// calc the new sizes
%newWidth = %this.maxWidth * %healthMultiplier;
%newHeight = %this.maxHeight * %healthMultiplier;
// update the size on the owner of this behavior
%this.owner.setSize(%newWidth, %newHeight);
}
function fishHealthManagementBehavior::onUpdate(%this)
{
// grab the scene time and figure out how long its been since the last update
%sceneTime = %this.owner.scenegraph.getSceneTime();
%diff = %sceneTime - %this.lastSceneTime;
// if its been the specified loss time then let decrease the health
if(%diff >= %this.healthLossTime)
{
// update the Health with the loss value then store this time as the last time
%this.updateHealth(%this.healthLossValue);
%this.lastSceneTime = %sceneTime;
}
}
Create a script file called "modifyHealth.cs" inside your Project Directory/game/behaviors folder, using the following code:
if(!isObject(fishModifyHealthBehavior))
{
%template = new BehaviorTemplate(fishModifyHealthBehavior);
%template.friendlyName = "Fish Tutorial Modify Health";
%template.behaviorType = "Gameplay";
%template.description = "Modify health control for our Fish Tutorial";
%template.addBehaviorField(healthModifier, "Value in which to modify the health by", integer, 2);
%template.addBehaviorField(minSpeed, "The min random speed to float down", float, 5);
%template.addBehaviorField(maxSpeed, "The max random speed to float down", float, 15);
}
function fishModifyHealthBehavior::onBehaviorAdd(%this)
{
// enable collision for sending and then enable the callback
%this.owner.collisionActiveSend = true;
%this.owner.collisionActiveReceive = false;
%this.owner.collisionCallback = true;
// disable physics
%this.owner.collisionPhysicsSend = false;
%this.owner.collisionPhysicsReceive = false;
// set the world limit
%this.owner.worldLimitMin = "-50 -45";
%this.owner.worldLimitMax = "50 45";
%this.owner.worldLimitMode = "NULL";
%this.owner.worldLimitCallback = true;
}
function fishModifyHealthBehavior::onAddToScene(%this, %scenegraph)
{
%this.startPositionY = %this.owner.getPositionY();
%this.respawn();
}
function fishModifyHealthBehavior::onCollision(%this, %dstObj, %srcRef, %dstRef, %time, %normal, %contacts, %points)
{
// lets update the health of the object we are colliding with
if(%dstObj.hasHealth)
{
%dstObj.updateHealth(%this.healthModifier);
%this.respawn();
}
}
function fishModifyHealthBehavior::onWorldLimit(%this, %limitMode, %limit)
{
switch$(%limit)
{
case "bottom":
%this.respawn();
}
}
function fishModifyHealthBehavior::respawn(%this)
{
%this.owner.setPositionY(%this.startPositionY);
%this.owner.setLinearVelocityY(getRandom(%this.minSpeed, %this.maxSpeed));
}
Now that we have our two behaviors, time to use them!
Next, drag a mine static sprite into the level just above the camera area, and a little to the side of your bubble. Then click on the Edit Tab. Add the "Fish Tutorial Modify Health" behavior just like you added the fish control behavior (select it from the drop down and click the plus button). Change the "healthModifier" value to -10 (this way it will subtract life).
Our final step to is to select our player fish, click the Edit Tab, and add the "Fish Tutorial Health Management" behavior. This behavior has a few different properties that I will explain:
The default values should work fine, though feel free to tweak to your delight. That is what TGB and behaviors are all about. When you are ready, hit the play button. You should be able to swim around and gather bubbles to increase in health and size and get hit by a mine to decrease in health and size. [edit] Adding Some BackgroundsNow that our base gameplay is done we add some background images as well as making minor changes to customize our fish game. There are three layers of background images:
[edit] ConclusionThe focus of this tutorial was not to complete a fully polished product, but to show how quickly you can prototype a game using Behaviors, TGB's Editors, and the Resource Manager. There are other tutorials, such as the non-behavior Fish Game and Fish Demo, which you can use to add on to this sample game. |







