In this tutorial we add a collection of enemies to the level, and make them move.
The movement of the enemies will be controlled by a new component called EnemyControllerComponent. Just like the PlayerControllerComponent, the EnemyControllerComponent will modify the velocity of the enemies, but instead of responding to keyboard input the EnemyControllerComponent will use the position of the left and right most enemies to follow the familiar move horizontally and drop down pattern of the classic space invaders games.
First we need a few parameters to describe link to the owning entities properties, as well as some variables the describe how the enemies will move and the size of the gameplay screen.
public class EnemyControllerComponent extends TickedComponent
{
public var PositionReference:PropertyReference = null;
public var VelocityReference:PropertyReference = null;
public var speed:Number = 75;
public var screenWidth:int = 480;
public var screenHeight:int = 384;
public var screenBuffer:int = 16;
All of the EnemyControllerComponents will be held in a static array called enemies. This will enable us to find those that are on the edge of the enemy block.
static protected var enemies:ArrayCollection = new ArrayCollection();
The yDrop variable holds the distance that the enemies have dropped down as part of their movement pattern.
static protected var yDrop:Number = 0;
The moveDown and direction variables define the current movement of the enemies.
static protected var direction:Boolean = true; static protected var moveDown:Boolean = false;
The leftEnemy, rightEnemy and bottomEnemy variables reference the EnemyControllerComponents of enemies that are on the edges of the enemy block.
static protected var leftEnemy:EnemyControllerComponent = null;
static protected var rightEnemy:EnemyControllerComponent = null;
static protected var bottomEnemy:EnemyControllerComponent = null;
public function EnemyControllerComponent()
{
super();
}
In the onAdd and onRemove functions we need to update the static enemies collection by adding or removing the current EnemyControllerComponent component and calling findEdgeEnemies.
protected override function onAdd():void
{
super.onAdd();
enemies.addItem(this);
findEdgeEnemies();
}
protected override function onRemove():void
{
super.onRemove();
enemies.removeItemAt(enemies.getItemIndex(this));
findEdgeEnemies();
}
The onTick function is where the direction that the enemies move is determined. First we grab a reference to the entities position and velocity, returning if either are null.
public override function onTick(tickRate:Number):void
{
var velocity:Point = owner.getProperty(VelocityReference);
var position:Point = owner.getProperty(PositionReference);
if (velocity == null ||
position == null)
return;
If this enemy is the first enemy in the enemies collection we check to see if a direction change is required. This logic has to be performed by one enemy once per frame – by doing the calculations with the first enemy in collection we make sure that all the enemies are moving in the same direction for the frame, because the moveDown or direction variables won’t be change during the frame (which they might if we did these calculations on one of the enemies in the middle of the collection). This does assume that the enemy entities are processed by PushButton in the same order that they are created, but (without actually digging through the code) that does seem to be the case.
if (this === enemies.getItemAt(0))
{
if (moveDown)
{
if (yDrop >= screenBuffer)
{
moveDown = false;
direction = !direction;
yDrop = 0;
}
}
else
{
var leftPositionposition:Point =
leftEnemy.owner.getProperty(PositionReference);
if (!direction && leftPositionposition.x <= screenBuffer)
moveDown = true;
var rightPositionposition:Point =
rightEnemy.owner.getProperty(PositionReference);
if (direction && rightPositionposition.x >
screenWidth - screenBuffer)
moveDown = true;
}
}
Finally, depending on the moveDown and direction variables, the velocity for the enemy is updated.
if (moveDown)
{
velocity.y = speed;
velocity.x = 0;
if (this === enemies.getItemAt(0))
yDrop += speed * tickRate;
}
else
{
velocity.y = 0;
velocity.x = direction?speed:-speed;
}
owner.setProperty(VelocityReference, velocity);
}
The findEdgeEnemies function scans the enemies collection to find enemies on the edge of the enemy block. These are then used to work out if the enemies should drop down to the next row, and eventually will be used to end the game when the enemies reach the bottom of the screen.
protected function findEdgeEnemies():void
{
leftEnemy = null;
rightEnemy = null;
bottomEnemy = null;
if (enemies.length > 0)
{
var leftX:int = -1;
var rightX:int = -1;
var bottomY:int = -1;
for each (var enemyController:EnemyControllerComponent in enemies)
{
var position:Point =
enemyController.owner.getProperty(PositionReference);
if (leftX == -1 || position.x < leftX)
{
leftX = position.x;
leftEnemy = enemyController;
}
if (rightX == -1 || position.x > rightX)
{
rightX = position.x;
rightEnemy = enemyController;
}
if (bottomY == -1 || position.y > bottomY)
{
bottomY = position.y;
bottomEnemy = enemyController;
}
}
}
}
}
The enemy template code gets the new EnemyControllerComponent.
The level1.xml file also include a the new enemy entity definitions.
In C++ an array is a set of consecutive objects of the same type, in memory. We see how to crea...
A database is a set of related tables. This is part 1, division 1 of a series I have on databas...
To easy way lean java programming language with a basic concepts which will help to build basic...
its an tutorial to make a virus /worm in C language...
cracking unix system password all about unix cracking it quite easily...
In this tutorial we add mouse interactivity to the scene....
In this tutorial we allow the view of the isometric scene to be moved with the mouse....
In this tutorial we show the height of an isometric object by adding a shadow....
In this tutorial we modify the appearance of the isometric cube at runtime....
In this tutorial we add some animated isometric boxes to the scene....