How to Build Tower Defense 2 — Multi-path Maps, Homing Missiles and Tower Merging

Play this game → View the full source →

What you will learn in this tutorial

Tower Defense 2 builds on the simple framework of the first game and stacks several richer features on top one at a time: multiple coexisting paths, flying enemies that travel in a straight line, homing missile bullets, tower merging for level-ups, and a three-layer explosion effect. Each part is straightforward on its own, so you can definitely follow along step by step.

① Build multi-path maps from polylines

In the original game we wrote each map cell by hand in a 2D array. Here we hand makePath() only the coordinates of the corners, and it fills in the cells between them. This makes it easy to put one to three paths on every stage.

function makePath(points) {
  var path = [];
  for (var i = 0; i < points.length - 1; i++) {
    var r1 = points[i][0], c1 = points[i][1];
    var r2 = points[i+1][0], c2 = points[i+1][1];
    var dr = r2 === r1 ? 0 : (r2 > r1 ? 1 : -1);
    var dc = c2 === c1 ? 0 : (c2 > c1 ? 1 : -1);
    var r = r1, c = c1;
    if (i === 0) path.push({r:r, c:c});
    while (r !== r2 || c !== c2) {
      r += dr; c += dc;
      path.push({r:r, c:c});
    }
  }
  return path;
}

// Example: a stage with two paths
var stage = {
  goal: [9, 7],
  paths: [
    makePath([[0,2],[4,2],[4,7],[9,7]]),
    makePath([[0,12],[6,12],[6,7],[9,7]])
  ]
};

By ending every path at the same goal coordinate, each map has exactly one goal cell. The spot where multiple paths converge just before the goal is a "hotspot" where enemies pile up — a great place to drop towers.

② Fly enemies straight to the goal, ignoring the path

Give an enemy type the isFlying: true flag and the flying ones skip the path completely, heading in a straight line to the goal coordinates. Spawn them off-screen, either from the top or from above the left/right edge.

function createFlyingEnemy(stage, spd, radius) {
  var goal = stage.goal;
  var gx = (goal[1] + 0.5) * cellW;
  var gy = (goal[0] + 0.5) * cellH;
  // Spawn from the top or from above the left/right edge
  var sx, sy;
  if (Math.random() < 0.6) {
    sx = Math.random() * canvasW;  sy = -radius * 2;
  } else if (Math.random() < 0.5) {
    sx = -radius * 2;  sy = Math.random() * canvasH * 0.4;
  } else {
    sx = canvasW + radius * 2;  sy = Math.random() * canvasH * 0.4;
  }
  var dx = gx - sx, dy = gy - sy;
  var d = Math.sqrt(dx*dx + dy*dy);
  return {
    x: sx, y: sy, targetX: gx, targetY: gy,
    vx: (dx/d) * spd * cellW,
    vy: (dy/d) * spd * cellW,
    flying: true
  };
}

// Inside the update loop: re-aim every frame and keep moving
var fdx = e.targetX - e.x;
var fdy = e.targetY - e.y;
var fd = Math.sqrt(fdx*fdx + fdy*fdy);
e.vx = (fdx / fd) * spd;
e.vy = (fdy / fd) * spd;
e.x += e.vx;
e.y += e.vy;
if (fd < e.radius * 0.8) {
  // Reached the goal — lose a life
}

Flying enemies can only be hit by Anti-Air or Missile towers. In the later stages you have to plan for the air, otherwise they fly straight past the goal.

③ Build a homing missile bullet

Simple chasing feels boring, so the homing missile fires off in a random direction first, then slowly curves back toward the target. That gives it a real missile-like arc.

// On fire: random initial velocity + homing timer
if (tower.homing) {
  var launchAngle = tower.angle + (Math.random() - 0.5) * Math.PI * 1.2;
  bullet.vx = Math.cos(launchAngle) * bullet.speed * 0.7;
  bullet.vy = Math.sin(launchAngle) * bullet.speed * 0.7;
  bullet.launchTimer = 18;
}

// On update: travel by vx/vy during launchTimer, blend toward target later
if (b.homing && b.launchTimer > 0) {
  b.launchTimer--;
  if (b.target && b.launchTimer < 12) {
    var ldx = b.target.x - b.x;
    var ldy = b.target.y - b.y;
    var ld = Math.sqrt(ldx*ldx + ldy*ldy);
    var blend = 0.10;
    b.vx = b.vx * (1 - blend) + (ldx/ld) * b.speed * blend;
    b.vy = b.vy * (1 - blend) + (ldy/ld) * b.speed * blend;
  }
  b.x += b.vx;  b.y += b.vy;
}

The missile gets unlimited range (range: 999, basically the whole screen). To keep things balanced, give each shot a fairly low damage.

④ Merge towers to level them up

When you try to place a tower of the same type and same level on top of an existing one, merge them instead of placing a new one. Levelling up boosts damage, range and fire rate all at once, making it a very gold-efficient upgrade.

var LEVEL_DAMAGE = [1.0, 1.7, 2.8];
var LEVEL_RANGE  = [1.0, 1.18, 1.38];
var LEVEL_RATE   = [1.0, 0.85, 0.7];  // shorter cooldown

function placeOrMergeTower(r, c) {
  var existing = findTowerAt(r, c);
  if (existing !== -1) {
    var et = towers[existing];
    if (et.type !== selectedTower) return;
    if (et.level >= 3) return;
    var def = TOWER_TYPES[selectedTower];
    if (gold < def.cost) return;
    gold -= def.cost;
    et.level += 1;
    et.damage   = def.damage   * LEVEL_DAMAGE[et.level - 1];
    et.range    = def.range    * LEVEL_RANGE[et.level - 1] * cellW;
    et.fireRate = def.fireRate * LEVEL_RATE[et.level - 1];
    return;
  }
  // Otherwise place a new tower...
}

Adding a flashy explosion effect on merge gives the action a satisfying click of feedback.

Wrap-up — taking it further

In this tutorial you built four core features: auto-generated multi-path maps, straight-line flying enemies, a homing missile bullet, and tower merging level-ups. To take it further, try a map editor, save and load, new enemy types, music and sound effects, or even a co-op or endless-wave mode.

FAQ

Q: What is different from the first game?

A: Both gameplay and visuals get a big upgrade — 10 stages, multiple paths, flying enemies, homing missile towers, tower merging, up to 10x speed, meteor strikes, and a three-layer explosion effect.

Q: Can a beginner build this?

A: If you read it feature by feature you can follow along, but we recommend doing the first Tower Defense tutorial first and then coming to this sequel.

Q: How long will it take?

A: You can get a working version in roughly one to several hours. Balancing the difficulty and adding more maps will keep it fun for longer.