How to Create a Tower Defense Game in AS2 – Part 3
Part 3: Adding Enemies
Welcome back. In this part of the tutorial, we are going to add enemies to the field and we’re going to program them to move through the paths.
Let’s begin by adding the enemy to the stage. Like the other symbols, we’re going to do it by creating an empty MovieClip and drawing the shape into it. In order to do this, however, we must first define some variables. Do this at the top of the code:
var currentEnemy:Number = 0;//the current enemy that we're creating from the array
var enemyTime:Number = 0;//how many frames have elapsed since the last enemy was created
var enemyLimit:Number = 12;//how many frames are allowed before another enemy is created
var enemyArray:Array = new Array();//this array will tell the function when to create an enemy
var enemiesLeft:Number;//how many enemies are left on the field
enemyArray = [//defining the array
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],//1's will just represent an enemy to be created
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],//another row means another level
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];
I’ve extensively commented on what each variable does. Next, we need to create an onEnterFrame() function with a few actions, along with a few other stuff. Program this into the bottom of the code:
createEmptyMovieClip('enemyHolder',_root.getNextHighestDepth());//create a movieclip that will hold the enemy
_root.onEnterFrame = function(){
makeEnemies();//we'll just make some enemies
}
function makeEnemies():Void{//this function will add enemies to the field
if(enemyTime < enemyLimit){//if it isn't time to make them yet
enemyTime ++;//then keep on waiting
} else {//otherwise
var theCode:Number = enemyArray[currentLvl-1][currentEnemy];//get the code from the array
if(theCode == 1){//if it's set as 1
//then create a new enemy and add it to the enemy holder
enemyHolder.createEmptyMovieClip('enemy'+currentEnemy,enemyHolder.getNextHighestDepth());
//now we're going to draw the enemy. It'll just be a tiny red circle
enemyHolder['enemy'+currentEnemy].beginFill(0xFF0000);//coloring them red gray
enemyHolder['enemy'+currentEnemy].moveTo(0, 2.5);//move the entire shape a certain way
//create 4 curves so that it'll look like a circle
enemyHolder['enemy'+currentEnemy].curveTo(0,10,5,10);
enemyHolder['enemy'+currentEnemy].curveTo(10,10,10,5);
enemyHolder['enemy'+currentEnemy].curveTo(10,0,5,0);
enemyHolder['enemy'+currentEnemy].curveTo(0,0,0,5);
enemyHolder['enemy'+currentEnemy].endFill();//end the fill
}
currentEnemy ++;//move on to the next enemy
enemyTime = 0;//and reset the time
}
}
Now, if you test out the game, a red dot should appear on the top left corner of the screen. But, this isn’t what we want for our game, is it? In order to place the enemy so that it’s right next to the start point, we’re going to have to add some code. Remember the variables startDir and finDir that we created all that time ago? If you don’t here’s what it should look like at around line 11:
var startDir:String;//the direction the enemies go when they enter
var finDir:String;//the direction the enemies go when they exit
var startCoord:Number;//the coordinates of the beginning of the road
Well, we’re going to use these variables. Find in the makeRoad() function where we create add in the SPECIAL DIRECTIONAL ROAD PIECE (around line 129). Add the following code to the bottom of that if statement:
if(lvlArray[i] == 'START'){//if this is a start block
//then define the startDir and StartCoord based on it's coordinates
if(roadHolder['block'+i]._x == 0){
_root.startDir = 'RIGHT';
_root.startCoord = roadHolder['block'+i]._y;
} else if (roadHolder['block'+i]._y == 0){
_root.startDir = 'DOWN';
_root.startCoord = roadHolder['block'+i]._x;
} else if (roadHolder['block'+i]._x == 525){
_root.startDir = 'LEFT';
_root.startCoord = roadHolder['block'+i]._y;
} else if (roadHolder['block'+i]._y == 275){
_root.startDir = 'UP';
_root.startCoord = roadHolder['block'+i]._x;
} else {
//this level won't work if not any of these values
}
} else if (lvlArray[i] == 'FINISH'){//if this is a finish block
//then define the finDir based on it's coordinates
if(roadHolder['block'+i]._x == 0){
_root.finDir = 'LEFT';
} else if (roadHolder['block'+i]._y == 0){
_root.finDir = 'UP';
} else if (roadHolder['block'+i]._x == 525){
_root.finDir = 'RIGHT';
} else if (roadHolder['block'+i]._y == 275){
_root.finDir = 'DOWN';
} else {
//this level won't work if not any of these values
}
}
Next, we have to take the variables we just defined in this code and make the enemy use them. We also have to make the enemy move along the path. Go back to the makeEnemies() function and add the following code in the if(theCode == 1){ statement:
//add a few variables to the enemy
enemyHolder['enemy'+currentEnemy].maxSpeed = 3;//how fast it can possibly go
enemyHolder['enemy'+currentEnemy].xSpeed = 0;
enemyHolder['enemy'+currentEnemy].ySpeed = 0;
//checking what the start direction is
if(_root.startDir == 'UP'){//if it's starting up
enemyHolder['enemy'+currentEnemy]._y = 300;//set the y value off the field
enemyHolder['enemy'+currentEnemy]._x = _root.startCoord;//make the x value where it should be
enemyHolder['enemy'+currentEnemy].xSpeed = 0;//make it not move horizontally
enemyHolder['enemy'+currentEnemy].ySpeed = -enemyHolder['enemy'+currentEnemy].maxSpeed;//make it move upwards
} else if(_root.startDir == 'RIGHT'){//and so on for other directions
enemyHolder['enemy'+currentEnemy]._x = -25;
enemyHolder['enemy'+currentEnemy]._y = _root.startCoord;
enemyHolder['enemy'+currentEnemy].xSpeed = enemyHolder['enemy'+currentEnemy].maxSpeed;
enemyHolder['enemy'+currentEnemy].ySpeed = 0;
} else if(_root.startDir == 'DOWN'){
enemyHolder['enemy'+currentEnemy]._y = -25;
enemyHolder['enemy'+currentEnemy]._x = _root.startCoord;
enemyHolder['enemy'+currentEnemy].xSpeed = 0;
enemyHolder['enemy'+currentEnemy].ySpeed = enemyHolder['enemy'+currentEnemy].maxSpeed;
} else if(_root.startDir == 'LEFT'){
enemyHolder['enemy'+currentEnemy]._x = 550;
enemyHolder['enemy'+currentEnemy]._y = _root.startCoord;
enemyHolder['enemy'+currentEnemy].xSpeed = -enemyHolder['enemy'+currentEnemy].maxSpeed;
enemyHolder['enemy'+currentEnemy].ySpeed = 0;
}
enemyHolder['enemy'+currentEnemy]._x += 5;//fixing the x value
enemyHolder['enemy'+currentEnemy]._y += 5;//fixing up the y value
enemyHolder['enemy'+currentEnemy].onEnterFrame = function(){//give it some functions
this._x += this.xSpeed;
this._y += this.ySpeed;
}
The final thing we have to do in this lesson is make the enemy turn when it should turn. To do this, we must go back to the Directional Block. We’re going to use the directional block to access all of the enemies coordinates. If the coordinates are close enough to the block, then it will make the enemy change direction. Find the if(String(lvlArray[i])){ statement in the makeRoad() function. Add this code to the end of it:
roadHolder['block'+i].directType = lvlArray[i];//accessing the type of block it is
roadHolder['block'+i].onEnterFrame = function(){//add some functions to this block
//then it'll act as a directioning block
for(i = 0;i<_root.enemyArray[currentLvl-1].length;i++){//create a loop
//if the enemy's coordinates are too close to this block
if(this._x >= _root.enemyHolder['enemy'+i]._x - _root.enemyHolder['enemy'+i]._width*.5
&& this._x +6<= _root.enemyHolder['enemy'+i]._x + _root.enemyHolder['enemy'+i]._width*.5
&& this._y >= _root.enemyHolder['enemy'+i]._y - _root.enemyHolder['enemy'+i]._height*.5
&& this._y +6<= _root.enemyHolder['enemy'+i]._y + _root.enemyHolder['enemy'+i]._height*.5){
//then move the enemy's direction based on what direction this block points to
if(this.directType == 'UP'){
_root.enemyHolder['enemy'+i].xSpeed = 0;
_root.enemyHolder['enemy'+i].ySpeed = -_root.enemyHolder['enemy'+i].maxSpeed;
} else if(this.directType == 'RIGHT'){
_root.enemyHolder['enemy'+i].xSpeed = _root.enemyHolder['enemy'+i].maxSpeed;
_root.enemyHolder['enemy'+i].ySpeed = 0;
} else if(this.directType == 'DOWN'){
_root.enemyHolder['enemy'+i].xSpeed = 0;
_root.enemyHolder['enemy'+i].ySpeed = _root.enemyHolder['enemy'+i].maxSpeed;
} else if(this.directType == 'LEFT'){
_root.enemyHolder['enemy'+i].xSpeed = _root.enemyHolder['enemy'+i].maxSpeed;
_root.enemyHolder['enemy'+i].ySpeed = 0;
}
}
}
}