Space Invaders Behavior?
by Kevin Epps · in Torque Game Builder · 04/13/2008 (5:59 pm) · 5 replies
Has anyone created a standard space invaders movement behavior? I'm trying to figure out the best and most efficient way of achieving this. Maybe assign all enemies to a group and moving all enemies down when on of them reaches a set world limit first, or something like that.
About the author
#2
Make a utility method for calculating the left and right most invader, which can run all the time or just when one dies...
Then have something like a simple finite state machine controlling what they do...
if leftmost invader is at or past the left bounds, move down x, then start moving right
if rightmost invader is at or past the right bounds, move down x, then start moving left
05/15/2008 (8:57 am)
You probably need individual objects ( animatedSprites ) for the invaders so they can handle collisions and die individually, so to facilitate moving them all together, one idea is to mount them all to one invisible "controller" object. Then that object is the only one that needs to have a behavior ( or just code ) controlling its movement.Make a utility method for calculating the left and right most invader, which can run all the time or just when one dies...
Then have something like a simple finite state machine controlling what they do...
if leftmost invader is at or past the left bounds, move down x, then start moving right
if rightmost invader is at or past the right bounds, move down x, then start moving left
#3
05/15/2008 (10:25 am)
Actually, I came up with one. Just forgot to post. You would to put all enemies in the set into one group # and pass that group # along with speeds, limits, and such into the behavior.//-----------------------------------------------------------------------------
// Torque Game Builder
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
if (!isObject(SpaceInvaderBehavior))
{
%template = new BehaviorTemplate(SpaceInvaderBehavior);
%template.friendlyName = "Space Invader Movement";
%template.behaviorType = "AI";
%template.description = "Invader style movement control";
%template.addBehaviorField(verticalSpeed, "Speed when moving vertically", float, 20.0);
%template.addBehaviorField(horizontalSpeed, "Speed when moving horizontally", float, 20.0);
%template.addBehaviorField(groupNumber, "Group Id for enemy group.", int, 0);
%template.addBehaviorField(leftBorder, "Left Area Border of Invader", float, 0.0);
%template.addBehaviorField(rightBorder, "Right Area Border of Invader", float, 100.0);
%template.addBehaviorField(downCap, "The distance of how far invader should move south before shifting", float, 10.0);
%template.addBehaviorField(horizontalSpeed, "Speed when moving horizontally", float, 20.0);
%template.addBehaviorField(startDirection, "Starting direction (left), (right), (up), (down).", string, "right");
}
function SpaceInvaderBehavior::onBehaviorAdd(%this)
{
%this.up = 0;
%this.down = 0;
%this.left = 0;
%this.right = 0;
%this.owner.enableUpdateCallback();
%this.startY = 0;
%this.leftside = 0;
%this.rightside = 0;
%this.startMove = false;
}
function SpaceInvaderBehavior::startMovement(%this)
{
%this.startMove = true;
switch$(%this.startDirection)
{
case "up":
%this.moveUp(1);
break;
case "down":
%this.moveDown(1);
break;
case "left":
%this.moveLeft(1);
break;
case "right":
%this.moveRight(1);
break;
}
}
/*function SpaceInvaderBehavior::onAnimationEnd(%this)
{
if(%this.owner.getAnimation() == %this.rtoiAnimation)
{
%this.owner.playAnimation(%this.iAnimation);
}
if(%this.owner.getAnimation() == %this.ltoiAnimation)
{
%this.owner.playAnimation(%this.iAnimation);
}
}*/
function SpaceInvaderBehavior::onUpdate(%this)
{
if(%this.startMove)
{
if((%this.owner.getPositionX() >= %this.rightBorder) && (%this.right == 1))
{
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
%enemy.moveRight(0);
%enemy.startY = %enemy.owner.getPositionY();
%enemy.rightside = 1;
%enemy.moveDown(1);
}
}
}
if((%this.owner.getPositionX() <= %this.leftBorder) && (%this.left == 1))
{
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
%enemy.moveLeft(0);
%enemy.startY = %enemy.owner.getPositionY();
%enemy.leftside = 1;
%enemy.moveDown(1);
}
}
}
if((%this.down == 1) && (%this.owner.getPositionY() - %this.startY >= %this.downCap))
{
echo("Work");
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
if(%enemy.leftside == 1)
{
%enemy.rightside = 0;
%enemy.leftside = 0;
%enemy.moveDown(0);
%enemy.moveRight(1);
}
else if(%enemy.rightside == 1)
{
%enemy.rightside = 0;
%enemy.leftside = 0;
%enemy.moveDown(0);
%enemy.moveLeft(1);
}
}
}
}
}
/*else
{
%shipinfo = %this.owner.getBehavior("ParallaxScrollObjectBehavior");
%shipbeh = %shipinfo.ship.getBehavior("ShooterControlsBehavior");
%sY = (%shipbeh.up - %shipbeh.down) * (mAbs(sceneWindow2D.getSceneGraph().scrollSpeedY) + %%shipinfo.ySpeed);
if(sceneWindow2D.getSceneGraph().scrollSpeedY == 0)
{
%sY = 0;
}
%this.owner.setLinearVelocityY(%sY);
}*/
}
function SpaceInvaderBehavior::onBehaviorRemove(%this)
{
%this.owner.disableUpdateCallback();
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
%enemy.moveRight(0);
%enemy.moveDown(0);
%enemy.moveLeft(0);
%enemy.moveUp(0);
%enemy.owner.setLinearVelocityX(0);
}
}
%this.owner.setLinearVelocityX(0);
}
function SpaceInvaderBehavior::updateMovement(%this)
{
%this.owner.setLinearVelocityX((%this.right - %this.left) * %this.horizontalSpeed);
%this.owner.setLinearVelocityY((%this.down - %this.up) * %this.verticalSpeed);
}
function SpaceInvaderBehavior::moveUp(%this, %val)
{
%this.up = %val;
%this.updateMovement();
}
function SpaceInvaderBehavior::moveDown(%this, %val)
{
%this.down = %val;
%this.updateMovement();
}
function SpaceInvaderBehavior::moveLeft(%this, %val)
{
%this.left = %val;
%this.updateMovement();
}
function SpaceInvaderBehavior::moveRight(%this, %val)
{
%this.right = %val;
%this.updateMovement();
}
#4
05/16/2008 (7:26 am)
This behavior doesnt work for me
#5
Sorry that behavior was tailored to my game's specs(startMove is false by default). Here try this one:
Also, make sure that you give each a group number and match it to the one you give the behavior.
05/16/2008 (7:45 am)
What's happening on your end? Are they just not moving?Sorry that behavior was tailored to my game's specs(startMove is false by default). Here try this one:
//-----------------------------------------------------------------------------
// Torque Game Builder
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
if (!isObject(SpaceInvaderBehavior))
{
%template = new BehaviorTemplate(SpaceInvaderBehavior);
%template.friendlyName = "Space Invader Movement";
%template.behaviorType = "AI";
%template.description = "Invader style movement control";
%template.addBehaviorField(verticalSpeed, "Speed when moving vertically", float, 20.0);
%template.addBehaviorField(horizontalSpeed, "Speed when moving horizontally", float, 20.0);
%template.addBehaviorField(groupNumber, "Group Id for enemy group.", int, 0);
%template.addBehaviorField(leftBorder, "Left Area Border of Invader", float, 0.0);
%template.addBehaviorField(rightBorder, "Right Area Border of Invader", float, 100.0);
%template.addBehaviorField(downCap, "The distance of how far invader should move south before shifting", float, 10.0);
%template.addBehaviorField(horizontalSpeed, "Speed when moving horizontally", float, 20.0);
%template.addBehaviorField(startDirection, "Starting direction (left), (right), (up), (down).", string, "right");
}
function SpaceInvaderBehavior::onBehaviorAdd(%this)
{
%this.up = 0;
%this.down = 0;
%this.left = 0;
%this.right = 0;
%this.owner.enableUpdateCallback();
%this.startY = 0;
%this.leftside = 0;
%this.rightside = 0;
}
function SpaceInvaderBehavior::startMovement(%this)
{
%this.startMove = true;
switch$(%this.startDirection)
{
case "up":
%this.moveUp(1);
break;
case "down":
%this.moveDown(1);
break;
case "left":
%this.moveLeft(1);
break;
case "right":
%this.moveRight(1);
break;
}
}
/*function SpaceInvaderBehavior::onAnimationEnd(%this)
{
if(%this.owner.getAnimation() == %this.rtoiAnimation)
{
%this.owner.playAnimation(%this.iAnimation);
}
if(%this.owner.getAnimation() == %this.ltoiAnimation)
{
%this.owner.playAnimation(%this.iAnimation);
}
}*/
function SpaceInvaderBehavior::onUpdate(%this)
{
if((%this.owner.getPositionX() >= %this.rightBorder) && (%this.right == 1))
{
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
%enemy.moveRight(0);
%enemy.startY = %enemy.owner.getPositionY();
%enemy.rightside = 1;
%enemy.moveDown(1);
}
}
}
if((%this.owner.getPositionX() <= %this.leftBorder) && (%this.left == 1))
{
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
%enemy.moveLeft(0);
%enemy.startY = %enemy.owner.getPositionY();
%enemy.leftside = 1;
%enemy.moveDown(1);
}
}
}
if((%this.down == 1) && (%this.owner.getPositionY() - %this.startY >= %this.downCap))
{
echo("Work");
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
if(%enemy.leftside == 1)
{
%enemy.rightside = 0;
%enemy.leftside = 0;
%enemy.moveDown(0);
%enemy.moveRight(1);
}
else if(%enemy.rightside == 1)
{
%enemy.rightside = 0;
%enemy.leftside = 0;
%enemy.moveDown(0);
%enemy.moveLeft(1);
}
}
}
}
}
function SpaceInvaderBehavior::onBehaviorRemove(%this)
{
%this.owner.disableUpdateCallback();
for(%i = 0; %i < %this.owner.scenegraph.getSceneObjectCount(); %i++)
{
if(%this.owner.scenegraph.getObject(%i).getGraphGroup() == %this.groupNumber)
{
%enemy = %this.owner.scenegraph.getObject(%i).getBehavior("SpaceInvaderBehavior");
%enemy.moveRight(0);
%enemy.moveDown(0);
%enemy.moveLeft(0);
%enemy.moveUp(0);
%enemy.owner.setLinearVelocityX(0);
}
}
%this.owner.setLinearVelocityX(0);
}
function SpaceInvaderBehavior::updateMovement(%this)
{
%this.owner.setLinearVelocityX((%this.right - %this.left) * %this.horizontalSpeed);
%this.owner.setLinearVelocityY((%this.down - %this.up) * %this.verticalSpeed);
}
function SpaceInvaderBehavior::moveUp(%this, %val)
{
%this.up = %val;
%this.updateMovement();
}
function SpaceInvaderBehavior::moveDown(%this, %val)
{
%this.down = %val;
%this.updateMovement();
}
function SpaceInvaderBehavior::moveLeft(%this, %val)
{
%this.left = %val;
%this.updateMovement();
}
function SpaceInvaderBehavior::moveRight(%this, %val)
{
%this.right = %val;
%this.updateMovement();
}Also, make sure that you give each a group number and match it to the one you give the behavior.
Torque Owner Anthony Ratcliffe
node = 0;
if(node==0);
{
//move to position
node++;
}
else if (node==2);
{
//move to next position
}
then when it reachs its world limit it takes you to a new screen saying u've lost
i'm more than willing to write a tut but i'm new myself