{"id":1394,"date":"2009-02-28T08:03:57","date_gmt":"2009-02-28T12:03:57","guid":{"rendered":"http:\/\/www.mrsunstudios.com\/?p=1394"},"modified":"2022-05-29T08:23:29","modified_gmt":"2022-05-29T12:23:29","slug":"tutorial-create-a-tower-defense-game-in-as3-part-3","status":"publish","type":"post","link":"http:\/\/www.mrsunstudios.com\/blog\/flash\/tutorial-create-a-tower-defense-game-in-as3-part-3\/","title":{"rendered":"Tutorial: Create a Tower Defense Game in AS3 &#8211; Part 3"},"content":{"rendered":"<div class=\"toc\">\n<h3>Table of Contents<\/h3>\n<ol>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/02\/tutorial-create-a-tower-defense-game-in-as3\/\">Setting up Level<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/02\/tutorial-create-a-tower-defense-game-in-as3-part-2\/\">Adding Turrets<\/a><\/li>\n<li class=\"c_chap\"><a href=\"http:\/\/mrsunstudios.com\/2009\/02\/tutorial-create-a-tower-defense-game-in-as3-part-3\/\">Adding Enemies<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/02\/tutorial-create-a-tower-defense-game-in-as3-part-4\/\">Making Turrets Attack Enemies<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/02\/tutorial-create-a-tower-defense-game-in-as3-part-5\/\">Winning\/Losing the Game<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/02\/tutorial-create-a-tower-defense-game-in-as3-part-6\/\">Expanding on the Game<\/a><\/li>\n<li><a href=\"http:\/\/mrsunstudios.com\/2009\/02\/tutorial-create-a-tower-defense-game-in-as3-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 us begin by first creating an <tt>Enemy<\/tt> class. Do this by creating a new external ActionScript file saved as &#8220;Enemy.as&#8221; and adding the following code to it:<\/p>\n<pre lang=\"actionscript\">\r\npackage{\r\n\t\/\/imports\r\n\timport flash.display.MovieClip;\r\n\timport flash.display.Sprite;\r\n\timport flash.events.*;\r\n\t\/\/defining the class\r\n\tpublic class Enemy extends MovieClip{\r\n\t\tprivate var _root:MovieClip;\r\n\t\tpublic var xSpeed:int;\/\/how fast it's going horizontally\r\n\t\tpublic var ySpeed:int;\/\/how fast it's going vertically\r\n\t\tpublic var maxSpeed:int = 3;\/\/how fast it can possibly go\r\n\t\t\r\n\t\tpublic function Enemy(){\r\n\t\t\tthis.addEventListener(Event.ADDED, beginClass);\r\n\t\t\tthis.addEventListener(Event.ENTER_FRAME, eFrameEvents);\r\n\t\t}\r\n\t\tprivate function beginClass(e:Event):void{\r\n\t\t\t_root = MovieClip(root);\/\/defining the root\r\n\t\t\t\r\n\t\t\t\/\/checking what the start direction is\r\n\t\t\tif(_root.startDir == 'UP'){\/\/if it's starting up\r\n\t\t\t\tthis.y = 300;\/\/set the y value off the field\r\n\t\t\t\tthis.x = _root.startCoord;\/\/make the x value where it should be\r\n\t\t\t\tthis.xSpeed = 0;\/\/make it not move horizontally\r\n\t\t\t\tthis.ySpeed = -maxSpeed;\/\/make it move upwards\r\n\t\t\t} else if(_root.startDir == 'RIGHT'){\/\/and so on for other directions\r\n\t\t\t\tthis.x = -25;\r\n\t\t\t\tthis.y = _root.startCoord;\r\n\t\t\t\tthis.xSpeed = maxSpeed;\r\n\t\t\t\tthis.ySpeed = 0;\r\n\t\t\t} else if(_root.startDir == 'DOWN'){\r\n\t\t\t\tthis.y = -25;\r\n\t\t\t\tthis.x = _root.startCoord;\r\n\t\t\t\tthis.xSpeed = 0;\r\n\t\t\t\tthis.ySpeed = maxSpeed;\r\n\t\t\t} else if(_root.startDir == 'LEFT'){\r\n\t\t\t\tthis.x = 550;\r\n\t\t\t\tthis.y = _root.startCoord;\r\n\t\t\t\tthis.xSpeed = -maxSpeed;\r\n\t\t\t\tthis.ySpeed = 0;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\/\/draw the actual enemy, it's just a red ball\r\n\t\t\tthis.graphics.beginFill(0xFF0000);\r\n\t\t\tthis.graphics.drawCircle(12.5,12.5,5);\r\n\t\t\tthis.graphics.endFill();\r\n\t\t}\r\n\t\tprivate function eFrameEvents(e:Event):void{\r\n\t\t\t\/\/move it based on x and y value\r\n\t\t\tthis.x += xSpeed;\r\n\t\t\tthis.y += ySpeed;\r\n\t\t\t\r\n\t\t\t\/\/checking what direction it goes when finishing the path\r\n\t\t\tif(_root.finDir == 'UP'){\/\/if it finishes at the top\r\n\t\t\t\tif(this.y <= -25){\/\/if the y value is too high\r\n\t\t\t\t\tdestroyThis();\/\/then remove this guy from the field\r\n\t\t\t\t}\r\n\t\t\t} else if(_root.finDir == 'RIGHT'){\/\/and so on for other directions\r\n\t\t\t\tif(this.x >= 550){\r\n\t\t\t\t\tdestroyThis();\r\n\t\t\t\t}\r\n\t\t\t} else if(_root.finDir == 'DOWN'){\r\n\t\t\t\tif(this.y >= 300){\r\n\t\t\t\t\tdestroyThis();\r\n\t\t\t\t}\r\n\t\t\t} else if(_root.startDir == 'LEFT'){\r\n\t\t\t\tif(this.x <= 0){\r\n\t\t\t\t\tdestroyThis();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\/\/remove this from stage when game is over\r\n\t\t\tif(_root.gameOver){\r\n\t\t\t\tdestroyThis();\r\n\t\t\t}\r\n\t\t}\r\n\t\tpublic function destroyThis():void{\r\n\t\t\t\/\/this function will make it easier to remove this from stage\r\n\t\t\tthis.removeEventListener(Event.ENTER_FRAME, eFrameEvents);\r\n\t\t\tthis.parent.removeChild(this);\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>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:<\/p>\n<pre lang=\"actionscript\">\r\nvar currentEnemy:int = 0;\/\/the current enemy that we're creating from the array\r\nvar enemyTime:int = 0;\/\/how many frames have elapsed since the last enemy was created\r\nvar enemyLimit:int = 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:int;\/\/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>Sweet. Now we can add an <tt>enterFrame<\/tt> function that'll create the enemies for us. Add this to the bottom of your code:<\/p>\n<pre lang=\"actionscript\">\r\naddEventListener(Event.ENTER_FRAME, eFrame);\/\/adding an eFrame function\r\nfunction eFrame(e:Event):void{\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:int = 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\tvar newEnemy:Enemy = new Enemy();\/\/then create a new enemy\r\n\t\t\tenemyHolder.addChild(newEnemy);\/\/and add it to the enemyholder\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>Also, we have to create an <tt>enemyHolder<\/tt>. 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 <tt>makeRoad()<\/tt> function:<\/p>\n<pre lang=\"actionscript\">\r\nvar enemyHolder:Sprite = new Sprite();\r\naddChild(enemyHolder);\r\n<\/pre>\n<p>Next, we have to count the amount of enemies that are going to be created. Add this code to the <tt>startGame()<\/tt> function:<\/p>\n<pre lang=\"actionscript\">\r\nfor(var i:int=0;i<enemyArray[currentLvl-1].length;i++){\r\n\tif(enemyArray[currentLvl-1][i] == 1){\r\n\t\tenemiesLeft ++;\r\n\t}\r\n}\r\n<\/pre>\n<p>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 <tt>beginClass()<\/tt> function:<\/p>\n<pre lang=\"actionscript\">\r\nif(directType == 'START'){\r\n\tif(directType == 'START'){\/\/if this is a start block\r\n\t\t\/\/then define the startDir and StartCoord based on it's coordinates\r\n\t\tif(this.x == 0){\r\n\t\t\t_root.startDir = 'RIGHT';\r\n\t\t\t_root.startCoord = this.y;\r\n\t\t} else if (this.y == 0){\r\n\t\t\t_root.startDir = 'DOWN';\r\n\t\t\t_root.startCoord = this.x;\r\n\t\t} else if (this.x == 525){\r\n\t\t\t_root.startDir = 'LEFT';\r\n\t\t\t_root.startCoord = this.y;\r\n\t\t} else if (this.y == 275){\r\n\t\t\t_root.startDir = 'UP';\r\n\t\t\t_root.startCoord = this.x;\r\n\t\t} else {\r\n\t\t\t\/\/this level won't work if not any of these values\r\n\t\t}\r\n\t} else if (directType == 'FINISH'){\/\/if this is a finish block\r\n\t\t\/\/then define the finDir based on it's coordinates\r\n\t\tif(this.x == 0){\r\n\t\t\t_root.finDir = 'LEFT';\r\n\t\t} else if (this.y == 0){\r\n\t\t\t_root.finDir = 'UP';\r\n\t\t} else if (this.x == 525){\r\n\t\t\t_root.finDir = 'RIGHT';\r\n\t\t} else if (this.y == 275){\r\n\t\t\t_root.finDir = 'DOWN';\r\n\t\t} else {\r\n\t\t\t\/\/this level won't work if not any of these values\r\n\t\t}\r\n\t}\r\n<\/pre>\n<p>Next, add this code to the <tt>eFrame()<\/tt> function:<\/p>\n<pre lang=\"actionscript\">\r\nif(directType != 'START' && directType != 'FINISH'){\/\/if this isn't a start of finish block\r\n\t\/\/then it'll act as a directioning block\r\n\tfor(var i:int = 0;i<_root.enemyHolder.numChildren;i++){\/\/create a loop\r\n\t\tvar enTarget = _root.enemyHolder.getChildAt(i);\/\/this will hold a certain enemy\r\n\t\t\/\/if the enTarget's coordinates are too close to this block\r\n\t\tif(this.x >= enTarget.x - enTarget.width*.5 && this.x <= enTarget.x + enTarget.width*.5\r\n\t\t&#038;&#038; this.y >= enTarget.y - enTarget.height*.5 && this.y <= enTarget.y + enTarget.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(directType == 'UP'){\r\n\t\t\t\tenTarget.xSpeed = 0;\r\n\t\t\t\tenTarget.ySpeed = -enTarget.maxSpeed;\r\n\t\t\t} else if(directType == 'RIGHT'){\r\n\t\t\t\tenTarget.xSpeed = enTarget.maxSpeed;\r\n\t\t\t\tenTarget.ySpeed = 0;\r\n\t\t\t} else if(directType == 'DOWN'){\r\n\t\t\t\tenTarget.xSpeed = 0;\r\n\t\t\t\tenTarget.ySpeed = enTarget.maxSpeed;\r\n\t\t\t} else if(directType == 'LEFT'){\r\n\t\t\t\tenTarget.xSpeed = enTarget.maxSpeed;\r\n\t\t\t\tenTarget.ySpeed = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<p>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.<\/p>\n<p>That's all for this part of the tutorial. Next time, we'll make the turret detect and attack the enemies!<\/p>\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-as3\/pt3\/source.swf\" \/><embed type=\"application\/x-shockwave-flash\" width=\"550\" height=\"400\" src=\"http:\/\/www.mrsunstudios.com\/obj\/tuts\/tower-defense-as3\/pt3\/source.swf\"><\/embed><\/object><\/p>\n<p><a href=\"http:\/\/www.mrsunstudios.com\/obj\/tuts\/tower-defense-as3\/pt3\/tower-defense-as3-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,8,4,6],"tags":[25,8,246,19,18,245,247,11],"_links":{"self":[{"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/posts\/1394"}],"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=1394"}],"version-history":[{"count":10,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/posts\/1394\/revisions"}],"predecessor-version":[{"id":1474,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/posts\/1394\/revisions\/1474"}],"wp:attachment":[{"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/media?parent=1394"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/categories?post=1394"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.mrsunstudios.com\/blog\/wp-json\/wp\/v2\/tags?post=1394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}