Oct 28
Tower Defense in AS3 - Part 1
In keeping with my desire to learn as much about how the game development world works, I have spent some time looking into developing simple games in Flash over the course of the last couple years. Recently, I renewed my pursuit of this game medium, and I have been striving to learn some of the ins and outs of Actionscript 3. Having written a handful of basic Flash applications in Actionscript 2 — from the loader and controls of a full media presentation to an MP3 player and dynamic slideshow — I feel I had a solid understanding of the principles of Flash, both in the timeline, layering and scripting realms.
However, when I began working with AS3, whole worlds began to open up as I saw the potential unleashed by implementing a much more true OOP support into the code base. One of the most useful things that AS3 encourages is the understanding and use of the layering hierarchy of sprites and movie clips on the stage. As you add children to specific sprites or movie clips, they inherit their parent’s visibility spectrum and appear truly as part of that element on the stage. This may well have been a feature of AS2 as well, but I never took the time to learn that aspect deeply enough, since I did most of my work from modifying timeline animations.
I decided some time ago that one of the best ways to learn Flash would be to write a game that implements many of the features, such as vector layering and stage positioning. Furthermore, with my addiction to Tower Defense (TD) style games, I thought it only fitting to develop one myself and share my learning progress with others who may also be interested in the same type of application. This post is the first in a series that will follow my progress from manually drawing the GUI on which the game will be played (this post) to creating the basic Creeps and Towers which will make up the substance of the game. For those who are anxious to get started and don’t want to read everything in detail, I will provide a download link at the close of each post with the full source for the project to that point.
So, without further ado, let’s look at a few assumptions I will be making in this series. First, I assume that you have a decent knowledge of the principles of Flash and Actionscript. Since this is more an implementation of technologies to reach an end, I do not want to get into the nuances of the language itself: you can use Google to figure that out. I will assume basic knowledge of the drawing tools (API) that Sprite objects and MovieClips can use to draw lines, circles, rectangles and other vectors. I will be building this entire game using only manually drawn sprites rather than images so that every post will work directly on anyone’s Flash install. Additionally, a good understanding of OOP (Object Oriented Programming) techniques is really a must to work well in AS3, so that is another assumption I will be making.
That being said, let’s jump right in.
Creating the Framework
Every game must have a solid base on which to build, and with Flash it is no different. We will be creating a base class, simply called TD that will act as our controller throughout the series. This TD class will have all of our static variables needed for location reference and any other overall game controls (including color customization). So, to start, let’s create our main FLA file, and then we will add our TD class to it. We want to keep our structure somewhat logical, so we will place all our AS files within a “td” directory and package them accordingly. In AS3, packages are determined based upon the directory relationship between the main FLA (or SWF) file and the included AS files. In this first lesson, we will be creating the stage or board on which our game will be played.
Simply put, we will have a main area which will contain the map and a control area to the right of our stage. We will simulate a transparency in the background to our controls, but we want it to be solid so that if we have a map where our creeps exit to the east, they are not visible underneath our controls. This Flash file shows what I mean by the controls appearing to be somewhat transparent while still hiding the creeps. The final product of this lesson will be this stage without the creeps displayed here. We will work on maps and creep movement in the next lesson.
So, start by creating a new FLA file with a stage 600×400 pixels. The background color doesn’t matter since we will be drawing our own background with the TD class in a moment. Save this file wherever your working directory will be. Within this directory, create a new folder named “td” which will house all our AS files — this also serves to set up our package for our game. Remember as we set up our files that in AS3, we package our classes within the “package” brackets rather than following the AS2 routine.
Drawing our Background
Create a new AS file within the “td” directory and call it TD.as. Now, frame in your TD class and set up the static member variables that will be used throughout our application:
package td {
import flash.display.Sprite;
/**
* Tower Defense class to handle all aspects of the game itself
*/
public class TD extends Sprite
{
// Config variables (all public static)
public static var base_width:Number = 600;
public static var base_height:Number = 400;
public static var map_width:Number = 480;
public static var map_height:Number = 300;
public static var gui_width:Number = 120;
public static var bg_color:uint = 0x0F2947;
public static var grid_color:uint = 0x29527F;
public static var grid_size:Number = 20;
// Display regions
private var guiMC:Sprite = new Sprite();
// Member variables of the game
private var ctrl:GuiControls;
}
}
For the most part, these variables will be self-explanatory, and you will notice that the majority of my classes extend the Sprite class. This allows me to layer my objects in the hierarchy I’m after without the extra bloat of loading in the additional MovieClip overhead until needed. You will notice that the private ctrl var references a GuiControls object which does not yet exist: we will create this object in a moment. For now, we need to flesh out a couple methods within our TD class to draw out the background grid for our display. This is as easy as iterating over the width and height of the stage (represented by base_width and base_height in our TD class) in increments of grid_size. I have chosen to use 20 pixels per grid unit, but you can feel free to modify or experiment with the results using different numbers, and in fact, I encourage you to do so.
Notice as well that there is the declaration of a guiMC sprite that will give us a handle into which we can draw our controls. This sprite is where we will hold the visuals from the ctrl variable we will create as well. Using this method of child sprites (or MovieClips), we can easily encapsulate all the visuals into regions in our display.
Now, let’s use the basic graphics API of the Sprite class to draw our background and add as a child of our TD object so that it is our bottom most visible layer (Keep in mind that these functions are member methods of the TD class):
drawBackground()
private function drawBackground()
{
// Draw the background color
graphics.beginFill(bg_color);
graphics.drawRect(0, 0, base_width, base_height);
graphics.endFill();
// Draw gridlines
graphics.lineStyle(1, grid_color);
for (var i = 0; i < base_width; i += grid_size)
{
graphics.moveTo(i, 0);
graphics.lineTo(i, base_height);
}
for (var j = 0; j < base_height; j += grid_size)
{
graphics.moveTo(0, j);
graphics.lineTo(base_width, j);
}
}
As you can see, in this method, we simply use the variables we defined for our base sizes to draw grid lines on top of the background rectangle we draw. All the colors used here are also defined as static member variables to be accessible from anywhere within our system. This allows for a great amount of customization when we want to change things up.
drawControls()
private function drawControls()
{
guiMC.x = base_width - gui_width;
ctrl = new GuiControls(gui_width, base_height);
guiMC.addChild(ctrl);
}
You can very easily tell what we are doing here. We instantiate a new GuiControls object, passing it the dimensions of our control region we wish to display, and attach it as a child to our guiMC member variable. This creates our controllable hierarchy for our rendering. Now that we have all the footwork in place, we can create our constructor method to instantiate our TD class.
TD()
public function TD()
{
// Draw background grid
drawBackground();
// Set up Controls HUD
drawControls();
addChild(guiMC);
}
Quite simply, when the TD object is created, it simply calls our drawBackground() method we created above, calls the drawControls() method, attaching the controls to the guiMC sprite, and then attaches the guiMC sprite to the TD object, making it visible on the stage. That’s really all there is to it. Now, if you were to run this code as it stands, you would get an error since the GuiControls class does not exist. To rectify that, we will create this class now and include it within our TD class definition file.
The GuiControls Class
This class is extremely straight forward, and at this time, it simply draws the background for the controls portion of our map, so I am just going to show the code for it here and let you read it:
package td.gui {
import flash.display.Sprite;
import td.TD;
public class GuiControls extends Sprite
{
private var bg_color:uint = 0xCCCCCC;
private var border_color:uint = 0x000000;
private var gui_width:Number;
private var gui_height:Number;
public function GuiControls(w, h)
{
gui_width = w;
gui_height = h;
drawBackground();
}
private function drawBackground()
{
// First, let's draw a duplicate background so anything passing under
// the control section disappears.
var bgDup = new Sprite();
bgDup.graphics.beginFill(TD.bg_color);
bgDup.graphics.drawRect(0, 0, gui_width, gui_height);
bgDup.graphics.endFill();
addChild(bgDup);
// Draw gridlines
bgDup.graphics.lineStyle(1, TD.grid_color);
for (var i = 0; i < gui_width; i += TD.grid_size)
{
bgDup.graphics.moveTo(i, 0);
bgDup.graphics.lineTo(i, gui_height);
}
for (var j = 0; j < gui_height; j += TD.grid_size)
{
bgDup.graphics.moveTo(0, j);
bgDup.graphics.lineTo(gui_width, j);
}
// Now, we draw our semi-transparent overlay that will house our controls
var overlay = new Sprite();
overlay.graphics.beginFill(bg_color, .6);
overlay.graphics.drawRect(0, 0, gui_width, gui_height);
overlay.graphics.endFill();
overlay.graphics.lineStyle(2, border_color, .8);
overlay.graphics.moveTo(0, 0);
overlay.graphics.lineTo(0, gui_height);
addChild(overlay);
}
}
}
From the package, you can tell that this class resides in a sub folder named “gui” within the “td” directory. In addition to creating this file, you will need to add the following import statement to the TD class definition file:
import td.gui.GuiControls;
With this minor adjustment, your classes are ready to be instantiated and used within the main FLA. When you are ready to test everything, select the first frame of your main FLA timeline and press F9 to bring up the Actionscript editing window. Once there, to instantiate and display our new TD object, simply add the following lines of code:
import td.TD; var game:TD = new TD(); addChild(game); stop();
If you have your files arranged correctly and have followed the packing instructions accurately, you should now have a working FLA file that will draw a grid background for your base. If something is not working properly, you can download the attached zip file that contains the entire demo we have reviewed for your perusal.
Next post will review creep movement and coordinate mapping…
3 Comments so far
Leave a comment
Awesome stuff so far…when is part 2 coming!
Not sure. I’ve already got the code base done for the first 3-4 parts, but I’ve got to find time to actually write it out. Work hit me pretty hard last week, but I hope to have part 2 done sometime this week.
Looking forward to se the next chapters of this.