{"id":1498,"date":"2009-04-25T08:03:10","date_gmt":"2009-04-25T12:03:10","guid":{"rendered":"http:\/\/www.mrsunstudios.com\/?p=1498"},"modified":"2022-05-29T08:23:29","modified_gmt":"2022-05-29T12:23:29","slug":"tutorial-create-a-tower-defense-game-in-as2-part-3","status":"publish","type":"post","link":"http:\/\/www.mrsunstudios.com\/blog\/flash\/tutorial-create-a-tower-defense-game-in-as2-part-3\/","title":{"rendered":"Tutorial: Create a Tower Defense Game in AS2 &#8211; Part 3"},"content":{"rendered":"<div class=\"toc\">\n<h3>Table of Contents<\/h3>\n<ol>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/04\/tutorial-create-a-tower-defense-game-in-as2\/\">Setting up Level<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/04\/tutorial-create-a-tower-defense-game-in-as2-part-2\/\">Adding Turrets<\/a><\/li>\n<li class=\"c_chap\"><a href=\"http:\/\/mrsunstudios.com\/2009\/04\/tutorial-create-a-tower-defense-game-in-as2-part-3\/\">Adding Enemies<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/04\/tutorial-create-a-tower-defense-game-in-as2-part-4\/\">Making Turrets Attack Enemies<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/04\/tutorial-create-a-tower-defense-game-in-as2-part-5\/\">Winning\/Losing the Game<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/04\/tutorial-create-a-tower-defense-game-in-as2-part-6\/\">Expanding on the Game<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/04\/tutorial-create-a-tower-defense-game-in-as2-part-7\/\">Finishing Touches<\/a><\/li>\n<\/ol>\n<\/div>\n<h3>Step 3: Adding Enemies<\/h3>\n<p>Welcome back. In this part of the tutorial, we are going to add enemies to the field and we&#8217;re going to program them to move through the paths.<\/p>\n<p>Let&#8217;s begin by adding the enemy to the stage. Like the other symbols, we&#8217;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:<\/p>\n<pre lang=\"actionscript\">\r\nvar currentEnemy:Number = 0;\/\/the current enemy that we're creating from the array\r\nvar enemyTime:Number = 0;\/\/how many frames have elapsed since the last enemy was created\r\nvar enemyLimit:Number = 12;\/\/how many frames are allowed before another enemy is created\r\nvar enemyArray:Array = new Array();\/\/this array will tell the function when to create an enemy\r\nvar enemiesLeft:Number;\/\/how many enemies are left on the field\r\nenemyArray = [\/\/defining the array\r\n\t\t\t[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\r\n\t\t\t[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],\/\/another row means another level\r\n\t\t\t[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]\r\n\t\t\t  ];\r\n<\/pre>\n<p>I&#8217;ve extensively commented on what each variable does. Next, we need to create an <tt>onEnterFrame()<\/tt> function with a few actions, along with a few other stuff. Program this into the bottom of the code:<\/p>\n<pre lang=\"actionscript\">\r\ncreateEmptyMovieClip('enemyHolder',_root.getNextHighestDepth());\/\/create a movieclip that will hold the enemy\r\n\r\n_root.onEnterFrame = function(){\r\n\tmakeEnemies();\/\/we'll just make some enemies\r\n}\r\n\r\nfunction makeEnemies():Void{\/\/this function will add enemies to the field\r\n\tif(enemyTime < enemyLimit){\/\/if it isn't time to make them yet\r\n\t\tenemyTime ++;\/\/then keep on waiting\r\n\t} else {\/\/otherwise\r\n\t\tvar theCode:Number = enemyArray[currentLvl-1][currentEnemy];\/\/get the code from the array\r\n\t\tif(theCode == 1){\/\/if it's set as 1\r\n\t\t\t\/\/then create a new enemy and add it to the enemy holder\r\n\t\t\tenemyHolder.createEmptyMovieClip('enemy'+currentEnemy,enemyHolder.getNextHighestDepth());\r\n\t\t\t\/\/now we're going to draw the enemy. It'll just be a tiny red circle\r\n\t\t\tenemyHolder['enemy'+currentEnemy].beginFill(0xFF0000);\/\/coloring them red gray\r\n\t\t\tenemyHolder['enemy'+currentEnemy].moveTo(0, 2.5);\/\/move the entire shape a certain way\r\n\t\t\t\/\/create 4 curves so that it'll look like a circle\r\n\t\t\tenemyHolder['enemy'+currentEnemy].curveTo(0,10,5,10);\r\n\t\t\tenemyHolder['enemy'+currentEnemy].curveTo(10,10,10,5);\r\n\t\t\tenemyHolder['enemy'+currentEnemy].curveTo(10,0,5,0);\r\n\t\t\tenemyHolder['enemy'+currentEnemy].curveTo(0,0,0,5);\r\n\t\t\tenemyHolder['enemy'+currentEnemy].endFill();\/\/end the fill\r\n\t\t}\r\n\t\tcurrentEnemy ++;\/\/move on to the next enemy\r\n\t\tenemyTime = 0;\/\/and reset the time\r\n\t}\r\n}\r\n<\/pre>\n<p>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 <tt>startDir<\/tt> and <tt>finDir<\/tt> that we created all that time ago? If you don't here's what it should look like at around line 11:<\/p>\n<pre lang=\"actionscript\">\r\nvar startDir:String;\/\/the direction the enemies go when they enter\r\nvar finDir:String;\/\/the direction the enemies go when they exit\r\nvar startCoord:Number;\/\/the coordinates of the beginning of the road\r\n<\/pre>\n<p>Well, we're going to use these variables. Find in the <tt>makeRoad()<\/tt> function where we create add in the <strong>SPECIAL DIRECTIONAL ROAD PIECE<\/strong> (around line 129). Add the following code to the bottom of that <tt>if<\/tt> statement:<\/p>\n<pre lang=\"actionscript\">\r\nif(lvlArray[i] == 'START'){\/\/if this is a start block\r\n\t\/\/then define the startDir and StartCoord based on it's coordinates\r\n\tif(roadHolder['block'+i]._x == 0){\r\n\t\t_root.startDir = 'RIGHT';\r\n\t\t_root.startCoord = roadHolder['block'+i]._y;\r\n\t} else if (roadHolder['block'+i]._y == 0){\r\n\t\t_root.startDir = 'DOWN';\r\n\t\t_root.startCoord = roadHolder['block'+i]._x;\r\n\t} else if (roadHolder['block'+i]._x == 525){\r\n\t\t_root.startDir = 'LEFT';\r\n\t\t_root.startCoord = roadHolder['block'+i]._y;\r\n\t} else if (roadHolder['block'+i]._y == 275){\r\n\t\t_root.startDir = 'UP';\r\n\t\t_root.startCoord = roadHolder['block'+i]._x;\r\n\t} else {\r\n\t\t\/\/this level won't work if not any of these values\r\n\t}\r\n} else if (lvlArray[i] == 'FINISH'){\/\/if this is a finish block\r\n\t\/\/then define the finDir based on it's coordinates\r\n\tif(roadHolder['block'+i]._x == 0){\r\n\t\t_root.finDir = 'LEFT';\r\n\t} else if (roadHolder['block'+i]._y == 0){\r\n\t\t_root.finDir = 'UP';\r\n\t} else if (roadHolder['block'+i]._x == 525){\r\n\t\t_root.finDir = 'RIGHT';\r\n\t} else if (roadHolder['block'+i]._y == 275){\r\n\t\t_root.finDir = 'DOWN';\r\n\t} else {\r\n\t\t\/\/this level won't work if not any of these values\r\n\t}\r\n}\r\n<\/pre>\n<p>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 <tt>makeEnemies()<\/tt> function and add the following code in the <tt>if(theCode == 1){<\/tt> statement:<\/p>\n<pre lang=\"actionscript\">\r\n\/\/add a few variables to the enemy\r\nenemyHolder['enemy'+currentEnemy].maxSpeed = 3;\/\/how fast it can possibly go\r\nenemyHolder['enemy'+currentEnemy].xSpeed = 0;\r\nenemyHolder['enemy'+currentEnemy].ySpeed = 0;\r\n\/\/checking what the start direction is\r\nif(_root.startDir == 'UP'){\/\/if it's starting up\r\n\tenemyHolder['enemy'+currentEnemy]._y = 300;\/\/set the y value off the field\r\n\tenemyHolder['enemy'+currentEnemy]._x = _root.startCoord;\/\/make the x value where it should be\r\n\tenemyHolder['enemy'+currentEnemy].xSpeed = 0;\/\/make it not move horizontally\r\n\tenemyHolder['enemy'+currentEnemy].ySpeed = -enemyHolder['enemy'+currentEnemy].maxSpeed;\/\/make it move upwards\r\n} else if(_root.startDir == 'RIGHT'){\/\/and so on for other directions\r\n\tenemyHolder['enemy'+currentEnemy]._x = -25;\r\n\tenemyHolder['enemy'+currentEnemy]._y = _root.startCoord;\r\n\tenemyHolder['enemy'+currentEnemy].xSpeed = enemyHolder['enemy'+currentEnemy].maxSpeed;\r\n\tenemyHolder['enemy'+currentEnemy].ySpeed = 0;\r\n} else if(_root.startDir == 'DOWN'){\r\n\tenemyHolder['enemy'+currentEnemy]._y = -25;\r\n\tenemyHolder['enemy'+currentEnemy]._x = _root.startCoord;\r\n\tenemyHolder['enemy'+currentEnemy].xSpeed = 0;\r\n\tenemyHolder['enemy'+currentEnemy].ySpeed = enemyHolder['enemy'+currentEnemy].maxSpeed;\r\n} else if(_root.startDir == 'LEFT'){\r\n\tenemyHolder['enemy'+currentEnemy]._x = 550;\r\n\tenemyHolder['enemy'+currentEnemy]._y = _root.startCoord;\r\n\tenemyHolder['enemy'+currentEnemy].xSpeed = -enemyHolder['enemy'+currentEnemy].maxSpeed;\r\n\tenemyHolder['enemy'+currentEnemy].ySpeed = 0;\r\n}\r\n\r\nenemyHolder['enemy'+currentEnemy]._x += 5;\/\/fixing the x value\r\nenemyHolder['enemy'+currentEnemy]._y += 5;\/\/fixing up the y value\r\n\r\nenemyHolder['enemy'+currentEnemy].onEnterFrame = function(){\/\/give it some functions\r\n\tthis._x += this.xSpeed;\r\n\tthis._y += this.ySpeed;\r\n}\r\n<\/pre>\n<p>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 <strong>Directional Block<\/strong>. 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 <tt>if(String(lvlArray[i])){<\/tt> statement in the <tt>makeRoad()<\/tt> function. Add this code to the end of it:<\/p>\n<pre lang=\"actionscript\">\r\nroadHolder['block'+i].directType = lvlArray[i];\/\/accessing the type of block it is\r\nroadHolder['block'+i].onEnterFrame = function(){\/\/add some functions to this block\r\n\t\/\/then it'll act as a directioning block\r\n\tfor(i = 0;i<_root.enemyArray[currentLvl-1].length;i++){\/\/create a loop\r\n\t\t\/\/if the enemy's coordinates are too close to this block\r\n\t\tif(this._x >= _root.enemyHolder['enemy'+i]._x - _root.enemyHolder['enemy'+i]._width*.5\r\n\t\t&& this._x +6<= _root.enemyHolder['enemy'+i]._x + _root.enemyHolder['enemy'+i]._width*.5\r\n\t\t&#038;&#038; this._y >= _root.enemyHolder['enemy'+i]._y - _root.enemyHolder['enemy'+i]._height*.5\r\n\t\t&& this._y +6<= _root.enemyHolder['enemy'+i]._y + _root.enemyHolder['enemy'+i]._height*.5){\r\n\t\t\t\/\/then move the enemy's direction based on what direction this block points to\r\n\t\t\tif(this.directType == 'UP'){\r\n\t\t\t\t_root.enemyHolder['enemy'+i].xSpeed = 0;\r\n\t\t\t\t_root.enemyHolder['enemy'+i].ySpeed = -_root.enemyHolder['enemy'+i].maxSpeed;\r\n\t\t\t} else if(this.directType == 'RIGHT'){\r\n\t\t\t\t_root.enemyHolder['enemy'+i].xSpeed = _root.enemyHolder['enemy'+i].maxSpeed;\r\n\t\t\t\t_root.enemyHolder['enemy'+i].ySpeed = 0;\r\n\t\t\t} else if(this.directType == 'DOWN'){\r\n\t\t\t\t_root.enemyHolder['enemy'+i].xSpeed = 0;\r\n\t\t\t\t_root.enemyHolder['enemy'+i].ySpeed = _root.enemyHolder['enemy'+i].maxSpeed;\r\n\t\t\t} else if(this.directType == 'LEFT'){\r\n\t\t\t\t_root.enemyHolder['enemy'+i].xSpeed = _root.enemyHolder['enemy'+i].maxSpeed;\r\n\t\t\t\t_root.enemyHolder['enemy'+i].ySpeed = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<h4>Final Product<\/h4>\n<p><center><object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" width=\"550\" height=\"400\" codebase=\"http:\/\/download.macromedia.com\/pub\/shockwave\/cabs\/flash\/swflash.cab#version=6,0,40,0\"><param name=\"src\" value=\"http:\/\/www.mrsunstudios.com\/obj\/tuts\/tower-defense-as2\/pt3\/source.swf\" \/><embed type=\"application\/x-shockwave-flash\" width=\"550\" height=\"400\" src=\"http:\/\/www.mrsunstudios.com\/obj\/tuts\/tower-defense-as2\/pt3\/source.swf\"><\/embed><\/object><\/p>\n<p><a href=\"http:\/\/www.mrsunstudios.com\/obj\/tuts\/tower-defense-as2\/pt3\/tower-defense-as2-source.zip\">Source Files (Zipped)<\/a><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Table of Contents Setting up Level Adding Turrets Adding Enemies Making Turrets Attack Enemies Winning\/Losing the Game Expanding on the Game Finishing Touches Step 3: Adding Enemies Welcome back. In this part of the tutorial, we are going to add enemies to the field and we&#8217;re going to program them to move through the paths. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[160,5,7,4,6],"tags":[25,7,246,19,18,245,247,11],"_links":{"self":[{"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/posts\/1498"}],"collection":[{"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/comments?post=1498"}],"version-history":[{"count":9,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/posts\/1498\/revisions"}],"predecessor-version":[{"id":1538,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/posts\/1498\/revisions\/1538"}],"wp:attachment":[{"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/media?parent=1498"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/categories?post=1498"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/tags?post=1498"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}