Flash Tutorial Links:
Play Games: HTML5 Tutorials:

How To Make A Tower Defense Game (Part 1)

So many monsters, so little ... towers

History of Tower Defense

This is a genre made popular by Warcraft III editor. The tower defense game was included as one of the bonus stages in Warcraft III, and so many defense mods have been created since then. It basically involves creating towers and placing them strategically to prevent waves and waves of monsters from advancing to a particular end point.

Towers have a variety of specialties to help you cope with the advancing monsters like being able to deal Area of Effect (AOE) damage, slow the monsters, or just plain nuke them to their deaths. In many Tower Defense games, the towers are also capable of being upgraded, giving them an extra boost in their power. Strategic placement, opportunistic upgrading of towers are hallmarks of a good tower defense player.

Game Scenario

Here, we focus on three different towers, the Fire Tower for plain old single target damage, the Ice Tower for a single target slow, as well as the Lightning Tower for AOE splash damage. With this arsenal at your disposal, you'll prevent 20 waves of advancing monsters.

Game Details

  1. Player can place Fire, Ice and Lightning Towers on various spots of the map.
  2. The player has to defend against 20 waves of monsters.
  3. Each monster's death or escape gives the player 15 gold.
  4. The player wins if all waves are killed.
  5. The player loses when 10 monsters break through his defenses.

Download the Game Files

The files you need to create this game can be downloaded from here.

Step 1 - Managing your FLA file

If you're not too familiar with how the framework is for this new tutorial, I strongly recommend that you head over to the Game Framework (Part 2) for these advanced tutorials first. It should give you a good idea of how I'm organising the FLA files now.

The timeline now contains the Menu, Game, GameWin and GameLose sections. Our focus will still be on the Game section since this is where all the ACTION takes place!

new timeline

As usual, let's jump into the startGame function and take a look at the initial values that we'll handle right at the start.

Step 2 - Setting initial values in your GameController.as

The startGame function is where you initialize all the variables and game states that your game should be defaulted to. Do refrain from putting these initialisations into your GameController() which is your constructor. This is a common mistake that I see. Remember that the constructor is called immediately when this swf runs, so you really don't have to initialise anything when the player is staring at the menu page.

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
public function startGame()
{
    currGold = C.START_GOLD;
    currWave = 0;
    maxWave = C.MAX_WAVE;
    
    placings = new Array();
    monsters = new Array();
    towers = new Array();
    bullets = new Array();
    
    timer = 0;
    life = C.PLAYER_START_LIFE;
    
    setupGame();
    
    //Initialise the UI event listeners
    mcGameUI.btnBuildFireTower.addEventListener(
            MouseEvent.CLICK, clickTowerFire);
    mcGameUI.btnBuildFireTower.addEventListener(
            MouseEvent.ROLL_OVER, showTowerFireHelp);
    mcGameUI.btnBuildFireTower.addEventListener(
            MouseEvent.ROLL_OUT, clearHelp);
    
    mcGameUI.btnBuildIceTower.addEventListener(
            MouseEvent.CLICK, clickTowerIce);
    mcGameUI.btnBuildIceTower.addEventListener(
            MouseEvent.ROLL_OVER, showTowerIceHelp);
    mcGameUI.btnBuildIceTower.addEventListener(
            MouseEvent.ROLL_OUT, clearHelp);
    
    mcGameUI.btnBuildLightningTower.addEventListener(
            MouseEvent.CLICK, clickTowerLightning);
    mcGameUI.btnBuildLightningTower.addEventListener(
            MouseEvent.ROLL_OVER, showTowerLightningHelp);
    mcGameUI.btnBuildLightningTower.addEventListener(
            MouseEvent.ROLL_OUT, clearHelp);
    
    mcGameUI.mouseEnabled = false;
    
    mcGameStage.addEventListener(Event.ENTER_FRAME,update);
    
    //Handle event when this game is being preloaded
    addEventListener(Event.ADDED_TO_STAGE, gameAddedToStage ); 
    
    //Handle situations when this game is being run directly
    if (stage != null)
    {
        stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
    }
}

Now, our game is starting to look more complex. =) Ok, let's tackle them bit by bit. Take a look at lines 80 to 83. placings is an array that will store all the possible locations that you can place your towers in. Specifically, if you open up the Library, there is a movieclip type called Placing. This is the one. monsters is the array that will store the monsters that come in waves to harass you. towers is the array that will store the towers that you place onto the map, and bullets will store all the bullets that are flying all over the place in the game.

Collectively, these 4 arrays will help us manage the game. In line 88, you can see the setupGame function which you have seen previously in the basic tutorials. If not, let's examine it again later.

Lines 91 to 96 add 3 event listeners to the towers that you see on the UI.

I've named them as such. But you would have noticed that I added a mcGameUI.btnBuildFireTower... etc. What is this mcGameUI? I've added this additional UI layer, just like I had this Game layer so that I can easily manage the UI. It will prove useful later on in more complex tutorials where I have to add or remove things dynamically from the UI. To see what this is exactly, it is just a blank movieclip (again, recall how I use a blank movieclip as the mcGameStage ... same concept here) that encompasses all the UI you put in during design time. It is accessed through the UI layer.

So to access the elements in the UI, we cannot just refer to it simply with btnBuildFireTower. Since it is a child of the overall UI movieclip, mcGameUI, now, we have to add the parent in front, hence, mcGameUI.btnBuildFireTower. Hope you recall your object oriented programming!

Anyway, back to lines 91 to 96. So what are these lines of code doing? They add a MouseEvent.CLICK listener which will trigger the clickTowerFire function when the player clicks on the button. We'll examine this later on. It adds a MouseEvent.ROLL_OVER so that the help text for the towers are displayed when you mouse moves over the icon, and the third event listener listens for ROLL_OUT events so that it can clear the text of the help.

Similarly, lines 98 to 103 does the same for the button btnBuildIceTower, and lines 105 to 110 does the same for the lightning tower.

Lines 112 is worth mentioning, since this is a very very common pitfall for game developers playing around with multiple layers of movieclips. I mentioned earlier that all these three buttons in your UI now belong to the parent mcGameUI. Since they are the children of this parent, when you click on them, what really happens is that the mcGameUI responds to those mouse events, and sometimes your child UI elements do not get them at all. So you can be sitting there feeling puzzled why some of the mouse events that you assigned to the various buttons in your mcGameUI just don't respond to you at all. Now you know! By assigning mcGameUI.mouseEnabled = false, you're telling Flash to not allow mcGameUI to respond to the mouse events at all.

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
private function setupGame()
{
    //Loop through all items on stage
    for (var i=0; i< mcGameStage.numChildren; i++)
    {
        var currObject = mcGameStage.getChildAt(i);
    
        //Look through the objects to see if it is class Placing
        if (currObject is Placing)
        {
            placings.push(currObject);
            currObject.gotoAndStop("off");
            
            currObject.addEventListener(MouseEvent.ROLL_OVER, 
            	turnOnPlacing);
            currObject.addEventListener(MouseEvent.ROLL_OUT, 
           		turnOffPlacing);					
        }
    }
}

In the setupGame function, we want to look through the mcGameStage and find out the Placing objects to be pushed into the array called placings. This is really the same style as how we looped through the game stage and searched for the Platform objects in the basic tutorial 8. Reason for this is that you, as the game designer, can freely design areas or strategic spots on the game map where the player is able to place a tower. If so, just drag a placing object out into mcGameStage.

The background map was drawn independently, so you may want to do some planning before you get your designer to draw this out. (Another way to do this would be to do the map in a tile-based fashion, but that is another tutorial. ^_^ ). You can see that about 36 placings have been dragged out. These 36 spots will be the valid spots that the player can build his towers upon. If you double-click and examine each Placing object further, you will see that I have already created 3 sections, properly labelled.

Eventually, we'll be making use of these sections to control whether the player can place his new towers upon it. Now, let's look at the code again.

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
private function setupGame()
{
    //Loop through all items on stage
    for (var i=0; i< mcGameStage.numChildren; i++)
    {
        var currObject = mcGameStage.getChildAt(i);
    
        //Look through the objects to see if it is class Placing
        if (currObject is Placing)
        {
            placings.push(currObject);
            currObject.gotoAndStop("off");
            
            currObject.addEventListener(MouseEvent.ROLL_OVER, 
            	turnOnPlacing);
            currObject.addEventListener(MouseEvent.ROLL_OUT, 
           		turnOffPlacing);					
        }
    }
}

Line 149 shows you that we push each placing object into the array called placings. Line 150 immediately sets each of the placings to their default label, which should be "off". Two event listeners are added to the placings, and the placings will respond to a mouse roll over, as well as a mouse roll out.

160
161
162
163
164
165
166
167
168
169
170
171
172
private function turnOnPlacing(evt:MouseEvent)
{
    var currPlacing = evt.currentTarget as Placing;
    if (currPlacing.currentLabel == "possible")
        currPlacing.gotoAndStop("on");
}
 
private function turnOffPlacing(evt:MouseEvent)
{
    var currPlacing = evt.currentTarget as Placing;
    if (currPlacing.currentLabel == "on")
        currPlacing.gotoAndStop("possible");
}

The above codes show what these two listeners do. Since all the placings share the same function (turnOnPlacing) that will be triggered when a mouse roll over event happens, this function must be able to tell them apart. Line 162 shows you how you can do that. evt.currentTarget will return you the placing which triggered this event, and "as Placing" simply casts it back into a Placing object.

The whole purpose of turnOnPlacing is to show the player that his mouse is currently hovering over a valid spot to place the tower. Of course, this means that the player must have clicked on a tower beforehand. As you'll see later, when a player clicks on a tower, all the placings which can hold a tower will go to their frame labelled "possible", turning the placing into a green colour. Lines 163 and 164 basically checks to see that if the mouse is hovering over such a possible placing, and jumps to the frame labelled "on", which will turn the placing white in colour.

As you can see, when the mouse hovers over a Placing that is at "possible" state, it will go to the "on" state, which is white. The function turnOffPlacing does the opposite and turns the "on" state back to a "possible" state when the mouse rolls away.

Strict Actionscript coders may not like this way of sneaking in "logic" into the frame labels. You can see that I'm responding differently with code depending on what a movieclip's frame label is. I agree, but for the purpose of the tutorial, and I don't see much issues ... yet ..., I'd continue using this style. Ideally, we should create a class attribute possibly to store such logic.

Step 3 - UI Functions

There are three pretty similar functions, clickTowerFire, clickTowerIce, and clickTowerLightning triggerred by clicking on the respective UI buttons. Let's examine what happens when you click on the fire tower.

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
private function clickTowerFire(evt:MouseEvent)
{
    //Check if the player has already clicked on a tower
    if (currTower != null)
    {
        mcGameUI.removeChild(currTower);
        currTower = null;
    }
    
    if (currGold >= C.TOWER_FIRE_COST)
    {
        currGold -= C.TOWER_FIRE_COST;
        
        //Create a Fire Tower now, referenced by the variable currTower
        currTower = new Tower_Fire();
        mcGameUI.addChild(currTower);
        
        //Turn on all placings
        for (var i in placings)
        {
            if (placings[i].canPlace)
                placings[i].gotoAndStop("possible");
        }
    }
}

What you see in line 177 is this variable currTower. This is central to the logic of what happens when you click on the buttons. In that line, it checks if this variable is not null (meaning it currently contains something already, which would mean that you have previously clicked another tower), and if so, it removes it from the mcGameUI and sets it to null. The reason for this code handles the situation whereby you click on say the button to build the Fire Tower, and so, currTower stores a reference to it. Say the player changes his mind, and then clicks on the button to build the Ice Tower, those lines 177 to 181 will thus remove the visual cue of the fireTower, and replaces it with the Ice Tower. currTower refers to this thing that you see when you click on a tower button.

As the player is hovering his mouse over the map to find a suitable location, this hovering tower helps to act as a visual cue as to what he is currently selecting for placement. This movieclip is added to the mcGameUI layer simply because we want it to float above all other game assets in the game at that point of time. Take note that when you place the tower, this movieclip of the tower will be added to the mcGameStage instead. The beauty of Flash layers!

Line 183 checks if you currently have enough gold to build this tower. Again, I choose to put these variables which we need to play with quickly during game balancing in a constants file, C.as. This allows you to go to a single file to make quick changes rather than scour through your entire code to find fragments of it.

Line 185 removes that amount of gold from you.

Line 188 creates a Tower_Fire and it is added to the mcGameUI as mentioned earlier. The reason why it follows your mouse cursor and moves along with it will be explained later in the game loop.

Lines 191 to 196 now loops through placings which has a reference to each Placing object, and checks if they currently allows placement of towers. This is locked through the use of a boolean attribute called canPlace which will be set to false once a tower is placed upon a Placing object. If this attribute is true (by default), it will "light up" to the green colour, which is actually the frame inside the Placing object labelled "possible". We'll see this again later when we take a look at the Tower class codes.

The functions clickTowerLightning and clickTowerLightning do basically the same thing as clickTowerFire, save for the fact that they create their own respective towers, so I'll leave it to you to read through them.

If you look at the following codes in lines 252 to 265, the functions showTowerFireHelp, etc, basically sets the help text when you mouse over the respective tower building icons.

Download the Game Files

The files you need to create this game can be downloaded from here.

To be continued ... in How To Make A Tower Defense Game (Part 2).

Flash Resources
Preloader FPS Display Sounds & Music
Keycodes Name Generator
Game Development Resources
Sprite Sheets