Tower Defense in AS3 – Part II
In this segment, we will be covering creep movement within a map, and to stay true with our original intent, everything in this tutorial will be drawn manually using the graphics package in the Sprite object within Flash. This way, we don’t have to worry about downloading images or the file size involved with such extras. Of course, were this a real TD game to be published, we would whip up some original artwork and animations to give our game a little more flair, but in this case, the simpler the better!
The code additions you can expect to find in Part II of this series include drawing our map (or “road”), creating and moving our creeps along that road and recognizing when a creep has completed the course successfully. Anyone familiar with Tower Defense games will recognize the importance of having a trigger to know when each creep finishes. Depending on the rules of your particular game, you may wish to have the creep run another circuit upon completion or simply vanish from existence, but in either case, there will be significant effects from that little guy getting away. Sometimes it costs us money to banish him back to the beginning, and in other games, we simply lose one of our lives and take one step closer to defeat.
I have chosen to simply have our creeps start a new lap as soon as they complete their current one. In this way, we already have our creep motion completed, and we simply have to attach any additional functionality we wish to add to our handler in order to affect our game. Now, let’s look at what approach I have taken in attempts to simplify the map creation and movement of our creeps.
Movement Concepts
Rather than going through line by line as I did in the previous post, I want to discuss the underlying principles to the code I have written and allow you to learn and modify the code as you will. Instead, I want to focus on the methodology and only review the code for very specific portions of our application. For starters, remember that we have divided our stage, map area and controls area into a grid of spaces, each of which is 20 x 20 pixels in size. This is the premise from which we are going to build our positioning for road and creeps alike — as well as for our towers in a future post.
We will assume that each grid point is represented by an X and Y coordinate. So, in essence, referencing coordinate [1, 1] would give us the uppermost left 20 x 20 pixel area of our map. With this in mind, we can quickly reference any grid point on our map, and this is exactly how we build our path. Rather than trying to calculate the exact pixel of where we want our creeps to move, we determine a series of points which they need to reach sequentially, and we let the creep move itself towards the next point on its path. To clarify, let’s assume we want to move a creep from the top, left corner across the map 10 grid points and then down 5 grid points. To do so, I could simply proved the creep with those 3 coordinates and set him in motion (ie, the points array would contain [1, 1], [1, 10], [5, 10]). Note: in our case, we are only supporting maps with straight lines for simplicity’s sake. You can actually use a version of this idea to allow for diagonal movement quite easily as well.
So, now, we understand the basic concept for how creeps can “smartly” move themselves around the map. Let’s look at some code that will help us create a Creep object that will be able to do just that. We will represent our creeps by simple circles for our project, and as such, remember that the point of origin is centered on the object. Understanding this will help us to easily center the creeps along our route instead of having them float high or low in our gridlines. If you open the Creep.as file from the code package available for download at the end of this post, look at the calculateGridPoint() method to see how we can pinpoint the center of a grid space.
Once we can calculate the exact location of each point to which the creep must travel, we can easily draw the creep and set his location to the starting point relative to the map. Examine the constructor for our Creep object, and notice that it takes an array of all coordinate points as its first argument. This is quite literally a multidimensional array of numbers, but these numbers correspond to our grid system. So, using our example from above, we would pass in the following array to each new creep we create:
var pts:Array = [ [1, 1], [10, 1], [10, 5] ];
Now, if we want our creeps to appear to enter the screen from a specific direction, we can easily simulate that by making the entry point “0″ in the direction from which we want the creeps to enter. So, rather than spawning the creeps directly into the top left corner [1, 1], we want to move left (X coordinate) one space in order to let the creeps move onto the screen — so [1, 1] becomes [0, 1] instead. We will do the exact same with our ending point as well.
Now that you have the principle of movement down, you can easily interpret the rest of the code for the Creep object and see how we know which direction to head. What you may find interesting is that, while the creep moves itself (the doMovement() method), it is actually our Wave object that calls doMovement() on each of the creeps in its ENTER_FRAME handler. By letting our wave manage the creeps, we can do calculations, checks, removals and anything else we need to have happen before the creep actually progresses each frame.
You will notice that while the creep handles its own speed, size and other visual attributes, it is the Wave that handles throttling the creep creation and maximum number of creeps. In this way, we can easily have the exact same code handle multiple waves of creeps, each with different speeds, strengths, weaknesses, maximum number, etc. What’s more, if we want to get really creative, we could even write the code to read the rules for each wave or even each game from an XML document. If we do this, we have, in essence, build a framework upon which we can build any Tower Defense game we want. At the time the go() method is called, it begins creating its creeps, throttling them and moving them. One reason I chose to handle our enemies in this fashion is that, as soon as the last of the creeps for a given wave is destroyed, we can completely remove the wave from the map and free up the memory for use elsewhere. Any management and cleanup of individual Sprites or MovieClips like this is a good idea to use.
So, this brings us back to our Level object. As we all know, the common Tower Defense game will have different maps to choose from (in ours, this is what the Level object represents). Once the level is chosen, it generates its own waves of creeps. In this way, it is actually the Level object that defines the points the creeps are to follow. Once we get further in the development process, the waves themselves will use an algorithm referencing the difficulty level chosen to know how many creeps to spawn and what strength they are to be. At the most basic level, all our Level object does is to manage two things: our actual visible road and our waves of creeps. By doing so, we can add the waves to a Sprite above our road to assure the creeps never get lost underneath, no matter what wave they are generated within.
The only remaining thing to examine in detail is the drawRoad() method that actually generates the visuals of the road within the level. You can look at this method and follow the calculation technique I have used. This draws the road along the exact path the level defines for the creeps; then the level passes along the array of points to each wave which in turn assigns the points for the creeps themselves. When everything is said and done, we have a working level to view.
Try playing around with the speed and size of the creeps as well as the spacing variable in the Wave class. By trying different combinations of these things, we can create very distinct “types” of creeps: from small, speedy ones to large, cumbersome, grouping ones.
There is also a doCreepEscape() method that is part of the overarching TD class that allows for us to add additional functionality to the exit of each creep. As it stands now, we simply increment the counter in the control panel to keep track of the number of escapees we have had.
Summary
This has been a whirlwind overview of the second phase of development, and while it may seem piecemeal to you as you read (indeed, it seems that this is how I am developing it in my spare time), I hope that the principles and concepts we cover will be useful to you. As in the previous phase of this series, you will find a link below that contains the complete source code and the working SWF file seen at the top of this post. Enjoy, and I will do my best to get Part III together before too long.
Garth Henson has been working professionally as a web developer for nearly 10 years. When not coding in PHP, JavaScript or Actionscript, he can usually be found trying to refine his photography skills.






Moc
13 Nov, 2008
This is just what I was looking for as I am learning AS3 in my spare time. This is one of my favorite type flash games. So to learn it as I learn Flash and AS3 is perfect.
Moc
Michael D
13 Nov, 2008
Awesome! This is being extremly helpful. Can’t wait for #3!
obsidian
13 Nov, 2008
Glad this is of some help so far. I realize that it’s not in typical “tutorial” mode that most coding posts would be, but I’m just writing as I develop. Perhaps I’ll try to write this up in a more structured training format in the future.
I’m not sure when, but next I’m going to try to write on the actual tower object itself…
john
14 Nov, 2008
Thank you! i read and learn from you. can’t wait for the 3 part.
Mike D
17 Nov, 2008
Any quess on when #3 will come out?
obsidian
18 Nov, 2008
Not sure on time yet. With the fist two, I had already written the code, and I just split it into the parts. For part three (and subsequent iterations), I need to figure out the best way to handle the code before I can write the entry.
Suffice to say, I’ll do it as quickly as I can
Robert
12 Dec, 2008
Hey i was looking at your code for the draw road and it didnt make any sence to me is thier any way you coulkd maby explain it more to me
Robert
12 Dec, 2008
NEVERMIND I FIGURED IT OUT ALL I HAD TO DO WAS EDIT THE LVL FILE TO CHANGE THE MAP
sry for the caps