Tower Defence: Part 2

Writing Tower Defence: Part 2

This is the second in a series of articles explaining the issues involved in writing a simple tower defence game. You can find the completed game on Kongregate, here, and the first article here. If you wish to follow along and have not read the first article, you can start with this archive.

This article adds the creeps, towers and interactivity that turns the framework established in the first into a working game.

I. What Is Tower Defence?

A tower defence game is one in which enemies (usually called creeps) attempt to move from a starting location to a target, and the player's job is to place defensive towers in order to stop them. The towers fire various sorts of missile at the creeps, automatically choosing targets where necessary. When a missile hits a creep, some damage is done, and when a creep takes enough damage it dies. When the player has let too many creeps through, the game is over.

There are two types: (i) 'free TD' (like the popular Desktop Tower Defence), where you can place towers anywhere and the creeps use A* pathfinding to find a valid route if you block their current one, and (ii) 'path TD' (like Onslaught), where creeps follow a fixed path and you cannot block them. Infinite TD is a path TD, because a free TD requires a lot of coding to do the pathfinding which is not particularly instructive in terms of producing a game.

So, we will clearly need coding constructs for certain features:

II. Creeps

Because all creeps' movement is effectively the same (move towards next target point, if you reach it, change to the next point on the path or take a life from the player), and because all their decisions require information from other parts of the map (the path), I choose to make creeps very light on code. All their decisions will be made in the Map class.

This is also a good time to introduce the idea of data driven programming. Instead of creating a different class for each type of creep, inheriting from a parent but setting different values of health, speed and so on, I only create one sort of creep 'object' (in fact an ActionScript associative array), but I create it from different data depending on its type. This will become clear in a few paragraphs.

For now we will add only one type of creep; the rest are repetition of the same idea. So, in terms of adding clips, you need only add the relevant image to the library:

      <!-- Creeps. Name of main clip should be 'creep_X' where X is the name in App.as -->
      <clip id="creep_GroundImage" import="res/creep_ground.png"/>
      <clip id="creep_Ground" class="Creep">
        <frame>
          <place id="creep_GroundImage" name="base" x="-7" y="-7" depth="1"/>
        </frame>
      </clip>

(uses image creep_ground.png)

This is simply an image centred on the (0,0) point of the main clip; with Flash I believe you can do this with a single clip by moving the registration point. Creep.as will encode the 'thinking' part of a creep and the map will deal with actually moving them, because movement is a generic thing that lots of map objects will want to do.

First we need to add a helpful function to Map:

	function move(o){
		var dx = (o.speed / _root.app.framerate) * o.direction[0];
		var dy = (o.speed / _root.app.framerate) * o.direction[1];
		o.x += dx; o.y += dy;
		o._x = o.x; o._y = o.y;
		return [dx, dy];
	}	

This function allows us to move any object around by setting two fields within it, speed (a scalar, i.e. single number) and direction (a 2-vector, i.e. two numbers, one for x and one for y). We will use this in a moment. Next, we need to add fields to Map to keep track of the creeps in play and the wave timing (and initialise them in initGame):

	var creeps = [], towers = [], bullets = [], waves = [];
	var lives, wave, money, nextwaveframe, creepdepth;

	function initGame(mapCol, pathCol){
		lives = 5;
		wave = 0;
		waves = []; creeps = [];
		creepdepth = 1;
		nextwaveframe = _root.app.frameno + 150;
		money = 250;
		towers = []; bullets = [];
		// ... (leave what was here already)
	}

You'll notice that we've jumped ahead slightly and initialised empty arrays for towers and bullets, and a value for money, too – we know we will need those later! creepdepth is a running counter that determines the depth of the next creep to be added, as you need to add each clip with a different depth to make them all appear. nextwaveframe is the frame number of the start of the next wave, and we leave a 5 second period before we start the first wave.

Next, let's add a field to App to define the different types of creep we know about, and how their values vary as the waves go by (so later creeps are stronger than earlier ones):

	var creepTypes = {
		Ground: {
			hp: 5, cash: 1, shield: 0.1, speed: 20, type: 'ground', n:20
		}
	};
	var creepFactors = {hp: 1.1, shield: 1.15, speed: 1.01, n: 1.01};

We only have one type at the moment, called Ground (remember that we called the movie clip creep_Ground), which comes in with a base HP of 5, a shield of 0.1 and a speed of 20 pixels per second, and 20 of them in a wave. The HP increases by 10% each turn, shield by 15% and speed and number by 1%.

Hopefully you're beginning to see the point of data-driven coding – it will be very easy to add different types of creep later on! We will also use a similar technique with towers.

Now, in the 'think' step of Map (onEnterFrame), find out if we are ready to start spawning a new wave:

function onEnterFrame(){
	if(_root.app.frameno >= nextwaveframe){
		// New wave
		var types = [], total = 0, type;
		type = {name: 'Ground', type:_root.app.creepTypes.Ground};

		var newwave = {type:type.type,  name:type.name, wave:wave, spawned:0,
			max:Math.floor(type.type.n * Math.pow(_root.app.creepFactors.n, wave)),
			nextspawn: _root.app.frameno
		};
		waves.push(newwave);
		nextwaveframe += 900; wave++;
	}
	...

This section checks whether the frame number is larger than the frame in which the next wave should start, and if so it creates a new wave object and adds it to the array of waves. Most of the wave's properties are obvious, but note that the number is increased depending on the frame number, and the nextspawn property, which is the frame in which the next enemy should spawn. We set nextspawn to the current frame because we want to spawn a new creep immediately. Finally, we increment the wave number and set the next wave to appear 900 frames (30s) in the future.

What we haven't done yet is to actually spawn a creep. That comes immediately after the code above:

	...
for(var wi = waves.length - 1; wi >= 0; wi--){
	var thiswave = waves[wi];
	if((thiswave.spawned < thiswave.max) && (_root.app.frameno >= thiswave.nextspawn)){
		// Spawn
		thiswave.spawned++; thiswave.nextspawn += 30;
		var spawn = creepContainer.attachMovie(
			'creep_' + thiswave.name,
			thiswave.name + creepdepth,
			creepdepth);
		creepdepth++;
		spawn._x = spawn.x = path[0][0]; spawn._y = spawn.y = path[0][1];
		spawn.alive = true;
		spawn.pathtarget = thiswave.type.ignoresPath ? path.length - 1 : 1;
		spawn.wave = thiswave.wave;
		for(var thing in _root.app.creepFactors){
			spawn[thing] = Math.floor(
				thiswave.type[thing] *
				Math.pow(_root.app.creepFactors[thing], thiswave.wave)
			);
		}
		spawn.type = thiswave.type;
		creeps.push(spawn);
	}
}
	...

What this does is check for each wave whether we are awaiting a spawn. If so, we put the next spawn point 30 frames (1s) ahead, create a clip and set some properties which we will use in creep thought and movement:

But wait, what is creepContainer? That is an empty movie clip that we want to place all our creeps into – when we clear the stage for a new game, it makes it much easier to remove all the previous game's creeps if we can just reinstantiate creepContainer. We will use the same trick for towers, too. So add the declarations near the top of Map.as – probably after bookmarking your current spot, as we haven't finished with onEnterFrame yet:

var creepContainer, towerContainer;

... and in initGame, add two lines to create the two clips:

		towerContainer = createEmptyMovieClip('towerContainer', 40);
		creepContainer = createEmptyMovieClip('creepContainer', 50);

As you know, adding a clip at the same depth as another one removes the old one, so by using a constant depth here we ensure that there is always exactly one tower container and one creep container. The main Map object is kept clear of the individual game entity clips.

So now we have code in onEnterFrame to create waves, and to spawn new creeps within a wave. There is one step still missing: the creeps should move along the path. First, go back to the end of onEnterFrame and continue with another loop through the creeps:

...
	for(var ci = creeps.length - 1; ci >= 0; ci--){
		creeps[ci].think(this);
		if(!creeps[ci].alive){ creeps.splice(ci, 1); continue; }
		move(creeps[ci]);
	}
}

That final } brings you to the end of onEnterFrame – for now! Notice the use of Array.splice – this method is very useful for getting rid of unwanted objects, and if you use this technique you must count through the array backwards as I do here. We don't want dead creeps filling up our array, so once a creep has died for any reason we remove it from the list.

Now we need to write the Creep class, and in particular a think method. A creep's thought is not complicated: if you reach a path node, start moving towards the next one, and if it was the last, remove a life from the player:

class Creep extends MovieClip {
	var pathtarget, direction, hp, shield, cash, type, wave, alive, x, y;
	function think(map){
		if(_root.dist2([_x, _y], map.path[pathtarget]) < 100){
			// Within 10px of a path node
			direction = null;
			pathtarget++;
		}
		if(!direction){
			if(pathtarget >= map.path.length){
				// Reached the end of its path
				map.changeLives(-1);
				alive = false; removeMovieClip();
				return;
			} else {
				direction = // norm(path[n] - location)
					_root.normalise(_root.vecadd(map.path[pathtarget], [x, y], 1, -1));
				_rotation = Math.atan2(direction[1], direction[0]) * 180 / Math.PI;
			}
		}
	}
}

There is one thing in this section which will be needed later: map.changeLives. Don't worry; ActionScript does not mind loose ends and this line will do nothing for now.

We do however make reference to several _root. functions (normalise, vecadd and dist2) which do not yet exist. These are an implementation of a subset of vector mathematics (if you don't know what that is, you might want to read up on it): normalisation, vector addition and subtraction, and squared distance. We need to write these functions, and inject them into _root! App's onLoad method is a perfect place to do this, so add the code to do so:

function onLoad(){
	...
	_root.dist2 = function(p1, p2){
		var r = 0;
		for(var i in p1) r += (p2[i]-p1[i]) * (p2[i]-p1[i]);
		return r;
	};
	_root.vecadd = function(v1, v2, c1, c2){
		var r = [];
		for(var i in v1) r[i] = (c1*v1[i]) + (c2*v2[i]);
		return r;
	};
	_root.vecmag = function(v){
		return Math.sqrt(_root.dist2(v, [0,0,0]));
	};
	_root.normalise = function(v){
		var m = _root.vecmag(v);
		for(var i in v) v[i] /= m;
		return v;
	};
	_root.vecdot = function(v1,v2){
		var r = 0;
		for(var i in v1) r += v1[i] * v2[i];
		return r;
	};
}

As well as the three functions we need right now, this also defines vecmag (magnitude) and vecdot (dot product). You may steal these functions wholesale, and a vector maths library is essential for a large proportion of games.

Hopefully the creep's 'intelligence' is now clear. First (in Map.onEnterFrame) we move the creep, using the move method we defined near the top of this article. Then (in Creep.think), if it's within 10 pixels of its target (the next node on the path), remove its direction vector and target the next point. Finally, if its direction is unknown, either it has finished the path (in which case, remove it and take a life from the player), or it has a new target, in which case set its direction vector to be the normalised vector difference between the target and its current location. This vector is normalised to ensure that speeds work correctly (a direction vector should always be of length 1), and the vector difference between two points always points along the direction between them.

Notice that I use dist2, not vecmag. It it usually best to do this, as square roots are computationally expensive whereas squaring the comparator is much less so – if it's a constant, you can just use the squared value. Also, notice the conversion from the return of atan2 (in radians) to degrees for the _rotation variable.

If you compile and run the game now, you should see waves of creeps moving around the path. One type only; we'll fill out the different creep types in article 3, if you can't see how to go about it already. (The tricky part is in onEnterFrame where the type is chosen.) You can start at this point by downloading this archive.

III. Towers

Of course, now we have creeps, we need some way to stop them. Tower defence games are all about the towers, and the time has come to add them.

Like the creeps, the definition of the in-game properties of each type of tower will be stored in data, but we need to create a graphical clip for each one. As with creeps, at this point for the sake of brevity I will add only one type of tower. However, unlike with creeps, towers have a significant amount of direct user interaction so our Tower class needs to have more content.

First things first: the movie clip. A tower consists of two parts, a fixed base and a rotatable gun. In SWFmill XML, that means:

      <clip id="TowerBase" import="res/towerbase.png" />
      <clip id="Gun1Image" import="res/gun1.png" />
      <clip id="Gun1"  x="-15" y="-15">
        <frame>
          <place id="Gun1Image" name="base" x="-15" y="-15" depth="1"/>
        </frame>
      </clip>
      <clip id="GunTower" class="Tower">
        <frame>
          <place id="TowerBase" name="base" x="-15" y="-15" depth="1"/>
          <place id="Gun1" name="gun" depth="16386"/>
        </frame>
      </clip>

(uses images towerbase.png and gun1.png)

The Gun1 clip's registration point must be in the middle of the circular part of the image, in order for the rotation to work correctly. Next, add the definition of the tower's properties to App:

	var towerTypes = {
		GunTower: [
			{cost: 50, rotate: 60, range: 100, cooldown: 20, type: 'bullet',
				projectilespeed: 400, projectilesize: 2, damage: 5,
				description: 'Gun tower 1: Basic projectile tower',
				canHit: {ground:true, air:true}, colour:0 }
		]
	};

The name of the field (GunTower) matches the name of the movie clip, so we know what to place. It is itself an array, at the moment with only one element, because we know that later we will want to be able to upgrade towers. GunTower[0] is the basic tower, GunTower[1], [2] and so on will be the upgraded versions. But we only need a basic tower for now.

These properties encapsulate the essential features of a TD tower:

The remaining properties define the type of missile this tower will fire, and that will be discussed later.

One nice feature of Infinite TD is that the menu buttons for placing a tower are actually using the same clip as the towers once placed in the game. This gives a good feel of 'I am taking one of these and placing it into the game world', and for a 2D game it is remarkably easy to accomplish. Remember right back at the beginning of article 1, when we built the initial XML document with all the top level items, we made an empty stub called TowerButtons placed at the top right? It is time to fill in one of those six empty spaces.

Replace the TowerButtons clip with this:

      <clip id="TowerButtons">
        <!-- Use the class name of the tower element as the name -->
        <frame>
          <place id="GunTower" name="GunTower" depth="1" x="40" y="40"/>
        </frame>
      </clip>

(If you're using a graphical environment, drag a Gun1 clip into the obvious place, and make it a child of TowerButtons.)

All towers have certain behaviours: if you mouse over them, they light up, and if you click them they begin placement (i.e. we add a clip to the Map and start moving it around). This needs to be represented in the Tower class, which will be behind both towers on the play area and the menu buttons. For now, let's just put in the menu code. Start a new file, Tower.as:

class Tower extends MovieClip {
	var placed = false, placing = false,	button = true;
	var mouseOver = false;
	var data;
	var level = 0;
	var base, gun, tags; // sub-elements
	var map;

	var radius = 16, baseradius = 15;

	var glowFilter, placeFilter, invalidFilter;

	function onEnterFrame(){
		if(button||placing){
			if(mouseOver){
				gun._rotation = (gun._rotation + data[level].rotate / _root.app.framerate) % 360;
			}
		}
	}

	function onLoad(){
		map = _root.app.map;
		if(!data) data = _root.app.towerTypes[_name];

		var filters = [];
		filters.push(new flash.filters.BevelFilter(1, 45, 0xFFFFFF, 0.5, 0, 0.3, 2, 4, 10, 2));
		glowFilter = new flash.filters.GlowFilter(0xFFD0A0, 0.4, 16, 16);
		placeFilter = new flash.filters.GlowFilter(0x00C000, 0.8, 16, 16);
		invalidFilter = new flash.filters.GlowFilter(0xFF0000, 0.8, 16, 16);
		gun.filters = filters;
	}

	function onRollOver(){
		mouseOver = true;
		if(button||placed){
			base.filters = [glowFilter];
		}
	}

	function onRollOut(){
		mouseOver = false;
		base.filters = [];
	}

	function onRelease(){
		if(button) map.startPlace(this);
		else if(placing){
			clear();
			map.endPlace(_x, _y);
		}
	}
}

That's a bit of a wall of code, but there's nothing complex. button, placing and placed define which state the tower is in – is it a menu button, is it being moved around pending placement by the user or is it already 'down' and part of the play area? onEnterFrame produces the nice effect that makes the gun rotate if you hover over it. onLoad creates a bunch of filters – a BevelFilter to produce the 3D effect on the gun at all rotations, and glow effects for mouse over and to indicate valid and invalid placement locations. The roll on and off handlers apply the glow effect when the mouse is over the tower.

onRelease calls two methods we haven't written yet in Map: startPlace and endPlace. If you run the game now, you should see a tower button that lights up and rotates when you put the mouse over it, but you can't actually place a tower onto the game area yet.

The one important note is that second line in onLoad. data is where the tower stores a copy of the definition of this tower type, and if it hasn't been given one, it uses the one with the same name as it has.

Placement is the responsibility of the map, because it requires a lot of context sensitive information (i.e. where the path goes, how much money the user has and what other towers are present). So the next step is to think about the mechanics of placing, and write startPlace and endPlace.

When placement begins, we need to create a new instance of the appropriate tower, and that tower should track with the mouse until it is either placed or cancelled. When placement ends, we need to fix the tower in position and take the money from the player.

So let's go ahead and code that. Add some methods to Map.as:

	function startPlace(tower){
		if(placing){
			placing.removeMovieClip();
			placing = null;
		}
		if(tower.data[0].cost > money) return;
		placing = towerContainer.attachMovie(tower._name, 'tower' + towers.length, towers.length);
		placing.button = false; placing.placing = true;
		placing._x = 3000;
		placing.data = tower.data;
		placing.level = 0;
		placing.showRange(30);
	}

	function endPlace(x, y){
		if(!placing) return;
		var placing = this.placing; this.placing = null;
		towertext._y = -1000;
		if(!canPlace(x,y,placing.radius,margin)){
			placing.removeMovieClip();
			return;
		}
		towers.push(placing);
		placing.placing = false; placing.placed = true;
		placing.clear();
		placing.nextfire = 0;
		money -= placing.data[placing.level].cost;
	}

	function onMouseMove(){
		if(placing){
			placing._x = _xmouse; placing._y = _ymouse;
			placing.base.filters =
				canPlace(placing._x, placing._y, placing.radius,margin) ?
				[placing.placeFilter] : [placing.invalidFilter];
			towertext._x = placing._x; towertext._y = placing._y + 3 + 0.5 * placing.radius;
		}
	}

You'll also need to declare placing (var placing; near the top), which is the variable we use to hold the tower which we are currently placing. There can only ever be one so a simple variable is fine. You also need a margin variable (var margin = 10;), which defines how much of the map area is hidden underneath the main menu image (around 10 pixels for mine) and is therefore 'dead zone' for tower placement.

Again, it's a large volume of code but nothing complicated. startPlace removes any previously placing tower, checks the money supply, adds the new one to towerContainer and changes it from a button to a placing tower. showRange is a method that doesn't exist yet (it will soon) which draws the range circle around the tower. The mouse move handler moves the tower to the mouse position, checks if the tower is valid in its current location and updates the filter appropriately. endPlace 'fixes' the tower by setting its placed property to true and adding it to the towers array.

endPlace does have two things of note. First, it clears the tower's graphical overlay – showRange will draw that and once we place the tower we don't want to see that any more. And second, it sets the nextfire property (to frame zero, which will always be in the past), which we will use when making decisions about firing.

We're still missing two pieces of the puzzle within Map: the function canPlace, which tells us whether a tower can be placed in a particular location, and the text field towertext which follows the tower and is used to display information about the location. The latter is easy: add a declaration in the ActionScript (var towertext;), and a subelement to the map in the XML; replace the current one line Map clip with this one:

      <textfield id="Text" text="" font="LightFont" width="100" height="75" size="10" color="#ffc000"/>
      <clip id="Map" class="Map" width="400" height="400" >
        <frame>
          <place id="Text" name="towertext" depth="17002" x="6000" />
        </frame>
      </clip>

(Or: Using a different editor, add a text field to the Map clip, call it towertext, and place it somewhere it can't be seen initially.)

canPlace is simple in idea, but less so in execution. What we want is for a position to be valid unless it is:

The first two are simple, the latter less so. Here is my canPlace:

	function canPlace(x, y, towerRadius, margin){
		if((x < towerRadius+margin) || (x+towerRadius+margin > w) ||
			(y < towerRadius+margin) || (y+towerRadius+margin > h)){
			towertext.text = 'Too close to edge';
			return false;
		}
		// Check each existing tower
		for(var i in towers){
			if(_root.dist2([x, y], [towers[i]._x, towers[i]._y]) <
				4 * (towerRadius * towerRadius)){
				towertext.text = 'Too close to another tower';
				return false;
			}
		}
		// Check distance each line segment
		for(var i = 1; i < path.length; i++){
			if(_root.disttoline2([x, y], path[i-1], path[i]) <
				4 * (towerRadius * towerRadius)){
				towertext.text = 'Too close to path';
				return false;
			}
		}
		towertext.text = 'Ok';
		return true;
	}

You also need to declare the field towertext (var towertext;). Notice the use of dist2 again to check the distance. What we're actually checking there is whether the two towers are less than 2 radii apart.

For the path, we are checking whether we are too close to any of the line segments. This uses a new _root function, disttoline2 (which gives the minimum distance between a point and a segment of a line) – back in the App.onLoad, inject that into root as with the vector functions:

		_root.disttoline2 = function(p, e1, e2){
			var linevec = _root.normalise(_root.vecadd(e2, e1, 1, -1));
			var pe1dotline = _root.vecdot(_root.vecadd(p, e1, 1, -1),linevec);
			if(pe1dotline < 0) return _root.dist2(p, e1);
			else if(_root.vecdot(_root.vecadd(p, e2, 1, -1),linevec) > 0) return _root.dist2(p, e2);
			else {
				var pointonline = _root.vecadd(e1, linevec, 1, pe1dotline);
				return _root.dist2(p, pointonline);
			}
		}

If you don't know this algorithm, don't worry about it – it does what we need. (If you want Bιzier curve segments on your path, it becomes harder!) Now it should be possible to select towers from the button in the upper right, drag them onto the map and place them. We don't see the range circle yet, so let's add that to Tower.as, as it is rather simple:

	function showRange(alpha){
		clear();
		var range = data[level].range;
		lineStyle(0,0,0);
		beginFill(0xFFFFC0, alpha);
		_root.drawCircle(this, range, 0, 0);
		endFill();
	}

At this point if you compile and run, you should be able to place towers in the same way as you can in the finished game. You can start from this point with this archive.

IV: Weaponry

So far we see creeps following the path, and we can select and place towers. But the towers cannot stop the creeps yet, because they cannot shoot at them.

The easy way to create a TD game is to create every bullet as a MovieClip. However, the Flash player is prone to slowing down with too many Clips on the screen at once, and late in a TD game you can easily have a lot of towers with one or more projectiles from each present simultaneously. So I use one Clip and paint the weapons fire using AS drawing commands.

So, in Map, declare a variable called overlay, and in initGame (just after you create creepContainer and towerContainer) add a clip called overlay to the map:

		overlay = createEmptyMovieClip('overlay', 1000);

We'll be storing the currently active bullets in the array called bullets, which we created when we added the creeps. A bullet is created by the thinking process of a tower, it moves by following its direction vector just like a creep, and it's destroyed by either moving out of range of its creator or by hitting an eligible enemy.

For the time being we're only interested in one sort of weapons fire: projectiles, fired directly at a target with a fixed direction, which when they hit a creep damage it and disappear. In part 3 I will show how to implement splash damage and laser weapons.

So, let's add some thinking code for the tower. Because a tower doesn't need to move, only rotate, we don't want to split this up like with creeps. First, think about what a tower's thought process is.

Now we know what it is that we want to code, we can go ahead and do it! In Tower.as, add a think method:

	function think(map){
		var data = this.data[this.level];
		var r2 = (data.range * data.range);
		if((!target) || (!target.alive) || (_root.dist2([_x, _y], [target._x, target._y]) > r2)){
			// No target, or out of range, so retarget
			var tscore = -10000;
			for(var ci in map.creeps){
				var creep = map.creeps[ci];
				if(!data.canHit[creep.type.type]) continue;
				var score = (_root.dist2([_x, _y], [creep._x, creep._y]) > r2) ? -5000 : 0;
				score -= Math.abs(getdw(creep));
				if(score > tscore){ tscore = score; target = creep; }
			}
		}
		if(!target) continue;
		var facing = face(target);
		if(facing && (_root.app.frameno >= nextfire) && (_root.dist2([_x, _y], [target._x, target._y]) < r2)){
			// Fire
			var bullet = {speed: data.projectilespeed, damage: data.damage, x: _x, y: _y, type:data.type, canHit:data.canHit, range: data.range, size:data.projectilesize };
			bullet.direction = _root.normalise([target._x - _x, target._y - _y]);
			bullet.colour = data.colour;
			bullet.source = this;
			map.bullets.push(bullet);
			nextfire = _root.app.frameno + data.cooldown;
		}
	}

You'll also need to declare variables target and nextfire (var target, nextfire;): the creep that is being targeted, and the next frame when the tower can fire. This thinking code uses some of the geometric utilities we pushed into _root, but also two new functions specific to the tower: face and getdw. face turns the tower to face a particular object, and getdw (really, d-omega) gets the angle through which the tower would need to turn in order to achieve that. Here are mine:

	function getdw(target){
		var targetAngle = Math.atan2(target._y - _y, target._x - _x) * 180 / Math.PI;
		var dw = targetAngle - gun._rotation;
		if(dw > 180) dw -= 360; else if(dw < -180) dw += 360;
		return dw;
	}

	function face(target){
		var dw = getdw(target);
		var maxdw = data[level].rotate / _root.app.framerate;
		if((dw >= -maxdw) && (dw <= maxdw)){ gun._rotation += dw; return true; }
		else if(dw < 0) gun._rotation -= maxdw;
		else gun._rotation += maxdw;

		return false;
	}	

To link your tower up with the map, in Map.onEnterFrame add a new loop:

		for(var ti = towers.length - 1; ti >= 0; ti--){
			towers[ti].think(this);
		}

Unlike creeps, towers can't die (not in this TD, anyway), so we don't need to worry about removing them.

Now your tower should rotate, and it will attempt to fire. However, we're not doing anything with that bullets array into which we are placing attempts to fire. Bullets are simple enough that we'll just process their actions in Map.onEnterFrame.

		for(var bi = bullets.length; bi >= 0; bi--){
			var bullet = bullets[bi];
			var ds = _root.vecmag(move(bullet));
			bullet.range -= ds;
			if(bullet.range <= 0){
				bullets.splice(bi, 1);
			}
		}

As well as moving the bullet, this code also kills the bullet once it has moved as far as its range allows. (Remember that move returns the vector by which the object was moved.)

A bullet's other action is to cause damage to creeps that it hits. I choose to put this in the creep's section of onEnterFrame, although it can also be coded in the bullet's section (it interacts with both). So within the creep loop within onEnterFrame, and add some code:

		...
		for(var ci = creeps.length - 1; ci >= 0; ci--){
			...
			for(var bi = bullets.length; bi >= 0; bi--){
				var bullet = bullets[bi];
				if(!bullets[bi].canHit[creeps[ci].type.type]) continue;
				if(creeps[ci].hitTest(bullet.x, bullet.y)){
					creeps[ci].takedamage(bullet.source, bullet.damage);
					bullets.splice(bi, 1);
				}
			}
		}
		...

Notice the use of the coordinate based hitTest, to test the creep against the non-clip bullet. Finally, on the logic side, we need to create Creep.takedamage, in Creep.as:

	function takedamage(source, damage){
		hp -= damage - shield;
	}

... and add some code to the Creep.think function to handle death:

		if(hp <= 0){
			alive = false;
			removeMovieClip();
			return;
		}	

At this point, your bullets will be firing, damaging creeps, and hopefully the creeps will be dying and disappearing. However, because the bullets have no graphical representation, you won't see anything – and seeing the weaponry is an important part of TD. As I said earlier, we will draw them on an overlay, with AS drawing commands. In Map.onEnterFrame, add another section (at the bottom of the function):

		// Redraw overlay
		overlay.clear();
		for(var bi in bullets){
			var bullet = bullets[bi];
			overlay.lineStyle(0,0,0);
			overlay.beginFill(bullet.colour);
			_root.drawCircle(overlay, bullet.size, bullet.x, bullet.y );
			overlay.endFill();
		}

If you haven't already got a drawCircle function, here is one (that you can add to App.onLoad) – I took this from a forum thread that I found through Google, so I claim no ownership rights over it, and it appears to have no licensing issues:

		_root.drawCircle = function(o, r, x, y) {
			// http://board.flashkit.com/board/archive/index.php/t-369672.html
			// r=circle radius, x,y=offset circle center coordinates within mcClip
			o.moveTo(x+r, y);
			// start drawing circle CCW at positive x-axis, at distance r from center(x+r)
			// 1st anchor point...x:(x+r), y:y
			o.curveTo(r+x,-0.4142*r+y,0.7071*r+x,-0.7071*r+y);
			// control point...x:radius+x offset, y:tan(pi/8)*radius+y offset
			// 2nd anchor point...x:cos(pi/4)*radius+x offset, y:sin(pi/4)*radius+y offset
			// becomes 1st anchor point for next curveTo
			o.curveTo(0.4142*r+x,-r+y,x,-r+y);
			// control point...x:cot(3pi/8)*radius+x offset, y:-radius+ y offset
			// 2nd anchor point...x:x offset,y:-radius+y offset
			// etc...
			o.curveTo(-0.4142*r+x,-r+y,-0.7071*r+x,-0.7071*r+y);
			o.curveTo(-r+x,-0.4142*r+y,-r+x, y);
			o.curveTo(-r+x,0.4142*r+y,-0.7071*r+x,0.7071*r+y);
			o.curveTo(-0.4142*r+x,r+y,x,r+y);
			o.curveTo(0.4142*r+x,r+y,0.7071*r+x,0.7071*r+y) ;
			o.curveTo(r+x,0.4142*r+y,r+x,y);
		};

Now you should be able to see the bullets, and see your carefully placed towers wiping out the creeps!

V. Debriefing

That's the end of the second article. By now you should have a playable TD game – creeps moving along the path, towers you can place and which turn and fire bullets, and bullets that damage and kill the creeps. In the final article I'll show you how to add the extra features that flesh out the game experience: lives, score, a game over screen, multiple creep and tower types, upgrades and the Kongregate API.

Appendix: Legal stuff