• home
  • forum
  • my
  • kt
  • download
  • How to Create a Tower Defense Game in AS3 - Pt 3

    Author: 2009-05-11 10:14:55 From:

    Step 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 us begin by first creating an Enemy class. Do this by creating a new external ActionScript file saved as “Enemy.as” and adding the following code to it:

    package{
    	//imports
    	import flash.display.MovieClip;
    	import flash.display.Sprite;
    	import flash.events.*;
    	//defining the class
    	public class Enemy extends MovieClip{
    		private var _root:MovieClip;
    		public var xSpeed:int;//how fast it's going horizontally
    		public var ySpeed:int;//how fast it's going vertically
    		public var maxSpeed:int = 3;//how fast it can possibly go
     
    		public function Enemy(){
    			this.addEventListener(Event.ADDED, beginClass);
    			this.addEventListener(Event.ENTER_FRAME, eFrameEvents);
    		}
    		private function beginClass(e:Event):void{
    			_root = MovieClip(root);//defining the root
     
    			//checking what the start direction is
    			if(_root.startDir == 'UP'){//if it's starting up
    				this.y = 300;//set the y value off the field
    				this.x = _root.startCoord;//make the x value where it should be
    				this.xSpeed = 0;//make it not move horizontally
    				this.ySpeed = -maxSpeed;//make it move upwards
    			} else if(_root.startDir == 'RIGHT'){//and so on for other directions
    				this.x = -25;
    				this.y = _root.startCoord;
    				this.xSpeed = maxSpeed;
    				this.ySpeed = 0;
    			} else if(_root.startDir == 'DOWN'){
    				this.y = -25;
    				this.x = _root.startCoord;
    				this.xSpeed = 0;
    				this.ySpeed = maxSpeed;
    			} else if(_root.startDir == 'LEFT'){
    				this.x = 550;
    				this.y = _root.startCoord;
    				this.xSpeed = -maxSpeed;
    				this.ySpeed = 0;
    			}
     
    			//draw the actual enemy, it's just a red ball
    			this.graphics.beginFill(0xFF0000);
    			this.graphics.drawCircle(12.5,12.5,5);
    			this.graphics.endFill();
    		}
    		private function eFrameEvents(e:Event):void{
    			//move it based on x and y value
    			this.x += xSpeed;
    			this.y += ySpeed;
     
    			//checking what direction it goes when finishing the path
    			if(_root.finDir == 'UP'){//if it finishes at the top
    				if(this.y <= -25){//if the y value is too high
    					destroyThis();//then remove this guy from the field
    				}
    			} else if(_root.finDir == 'RIGHT'){//and so on for other directions
    				if(this.x >= 550){
    					destroyThis();
    				}
    			} else if(_root.finDir == 'DOWN'){
    				if(this.y >= 300){
    					destroyThis();
    				}
    			} else if(_root.startDir == 'LEFT'){
    				if(this.x <= 0){
    					destroyThis();
    				}
    			}
     
    			//remove this from stage when game is over
    			if(_root.gameOver){
    				destroyThis();
    			}
    		}
    		public function destroyThis():void{
    			//this function will make it easier to remove this from stage
    			this.removeEventListener(Event.ENTER_FRAME, eFrameEvents);
    			this.parent.removeChild(this);
    		}
    	}
    }

    Now that’s a lot of code. The next thing we have to do is to add a function in the main “source.fla” that will add these guys to the field. But, let’s first create a bunch of variables that’ll help with the process. It’ll be simple. Just define them variable where all others are defined:

    var currentEnemy:int = 0;//the current enemy that we're creating from the array
    var enemyTime:int = 0;//how many frames have elapsed since the last enemy was created
    var enemyLimit:int = 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:int;//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]
    			  ];

    Sweet. Now we can add an enterFrame function that’ll create the enemies for us. Add this to the bottom of your code:

    addEventListener(Event.ENTER_FRAME, eFrame);//adding an eFrame function
    function eFrame(e:Event):void{
    	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:int = enemyArray[currentLvl-1][currentEnemy];//get the code from the array
    		if(theCode == 1){//if it's set as 1
    			var newEnemy:Enemy = new Enemy();//then create a new enemy
    			enemyHolder.addChild(newEnemy);//and add it to the enemyholder
    		}
    		currentEnemy ++;//move on to the next enemy
    		enemyTime = 0;//and reset the time
    	}
    }

    Also, we have to create an enemyHolder. We should do this after the road is put down, so all the enemies will appear on top of it. Add this code right after we run the makeRoad() function:

    var enemyHolder:Sprite = new Sprite();
    addChild(enemyHolder);

    Next, we have to count the amount of enemies that are going to be created. Add this code to the startGame() function:

    for(var i:int=0;i<enemyArray[currentLvl-1].length;i++){
    	if(enemyArray[currentLvl-1][i] == 1){
    		enemiesLeft ++;
    	}
    }

    Now, there is one final thing to do in order to make these enemies work. Find the “DirectBlock.as” file for me, would you? Add this code to the beginClass() function:

    if(directType == 'START'){
    	if(directType == 'START'){//if this is a start block
    		//then define the startDir and StartCoord based on it's coordinates
    		if(this.x == 0){
    			_root.startDir = 'RIGHT';
    			_root.startCoord = this.y;
    		} else if (this.y == 0){
    			_root.startDir = 'DOWN';
    			_root.startCoord = this.x;
    		} else if (this.x == 525){
    			_root.startDir = 'LEFT';
    			_root.startCoord = this.y;
    		} else if (this.y == 275){
    			_root.startDir = 'UP';
    			_root.startCoord = this.x;
    		} else {
    			//this level won't work if not any of these values
    		}
    	} else if (directType == 'FINISH'){//if this is a finish block
    		//then define the finDir based on it's coordinates
    		if(this.x == 0){
    			_root.finDir = 'LEFT';
    		} else if (this.y == 0){
    			_root.finDir = 'UP';
    		} else if (this.x == 525){
    			_root.finDir = 'RIGHT';
    		} else if (this.y == 275){
    			_root.finDir = 'DOWN';
    		} else {
    			//this level won't work if not any of these values
    		}
    	}

    Next, add this code to the eFrame() function:

    if(directType != 'START' && directType != 'FINISH'){//if this isn't a start of finish block
    	//then it'll act as a directioning block
    	for(var i:int = 0;i<_root.enemyHolder.numChildren;i++){//create a loop
    		var enTarget = _root.enemyHolder.getChildAt(i);//this will hold a certain enemy
    		//if the enTarget's coordinates are too close to this block
    		if(this.x >= enTarget.x - enTarget.width*.5 && this.x <= enTarget.x + enTarget.width*.5
    		&& this.y >= enTarget.y - enTarget.height*.5 && this.y <= enTarget.y + enTarget.height*.5){
    			//then move the enemy's direction based on what direction this block points to
    			if(directType == 'UP'){
    				enTarget.xSpeed = 0;
    				enTarget.ySpeed = -enTarget.maxSpeed;
    			} else if(directType == 'RIGHT'){
    				enTarget.xSpeed = enTarget.maxSpeed;
    				enTarget.ySpeed = 0;
    			} else if(directType == 'DOWN'){
    				enTarget.xSpeed = 0;
    				enTarget.ySpeed = enTarget.maxSpeed;
    			} else if(directType == 'LEFT'){
    				enTarget.xSpeed = enTarget.maxSpeed;
    				enTarget.ySpeed = 0;
    			}
    		}
    	}
    }

    Phew! That was a lot of code, wasn’t it? Well, what these snippets of code do is simply direct the enemies to where they should start and where they should go.

    That’s all for this part of the tutorial. Next time, we’ll make the turret detect and attack the enemies!

    Final Product

    Source Files (Zipped)

    discuss this topic to forum

    relation tutorial

    No information

    Category

      3D (36)
      Math Physics (18)
      3rd Party (10)
      Navigation (70)
      Actionscripting (228)
      Optimization (17)
      Animation (166)
      Projector (11)
      Audio (54)
      Special Effects (170)
      Backend (26)
      Text Effects (89)
      Drawing (34)
      Tips and Techniques (51)
      Dynamic Content (34)
      Tricks (8)
      Games (109)
      Utilities (23)
      Getting Started (96)
      Video (59)
      Interactivity (46)
      Web Design (35)

    New

    Hot