Loading...
Loading...
Build a tower defense: enemies pathing along lanes, wave spawning, towers that auto-target and fire, an economy, and lives. Use for a tower-defense/wave-defense game, or balancing waves and economy.
npx skill4agent add gamedev-skills/awesome-gamedev-agent-skills tower-defensefps-shootersurvival-craftinggame-ai| Knob | Effect | Notes |
|---|---|---|
| Enemy HP growth/wave | upgrade pressure | Geometric ~1.1–1.2× (refs). |
| Income vs. HP curves | difficulty | Player should almost afford each wave. |
| Tower DPS / range / cost | tower identity | Cheap+wide vs. expensive+tall. |
| Targeting priority | optimal placement | Changes play more than raw stats. |
| Enemy variety | counters one-build wins | Fast / armored / flying / swarm / boss. |
| Leak penalty | stakes | Cost lives and lost bounty. |
| Upgrade vs. build economy | strategy depth | Diminishing upgrade returns. |
| Wave pacing | tension curve | Spike → breather → spike, not monotonic. |
# Pseudocode. A wave is data: a list of (enemy_type, count, spacing). Spawn over time.
wave = [ ("grunt", 10, 0.5), ("runner", 5, 0.3), ("tank", 2, 1.0) ]
def run_wave(wave):
for enemy_type, count, spacing in wave:
for _ in range(count):
spawn_enemy(enemy_type, at=path[0]) # enter at the path start
wait(spacing) # seconds between spawns (use a timer/coroutine)
# wave clears when all spawned enemies are dead or have leaked# Pseudocode. "First" (furthest along path) is the standard default for stopping leaks.
def acquire_target(tower, enemies, mode="first"):
in_range = [e for e in enemies if distance(tower.pos, e.pos) <= tower.range]
if not in_range: return None
if mode == "first": return max(in_range, key=lambda e: e.progress) # furthest along path (stop leaks)
if mode == "last": return min(in_range, key=lambda e: e.progress) # least progress (guard the entrance)
if mode == "closest": return min(in_range, key=lambda e: distance(tower.pos, e.pos))
if mode == "strongest":return max(in_range, key=lambda e: e.hp) # burn down tanks first
if mode == "weakest": return min(in_range, key=lambda e: e.hp) # secure kills / last-hit bounty
return in_range[0]# Pseudocode. One tower's damage to one enemy crossing its range.
tower_dps = tower.damage * tower.fire_rate
time_in_range = tower.range_coverage_length / enemy.speed
damage_dealt = tower_dps * time_in_range
# Lane holds if summed damage_dealt from covering towers >= enemy.hp (per enemy). See refs.dtdtgame-aigodot-2d-movementunity-navmeshgodot-tilemapunity-tilemap-2dlevel-designgodot-resourcesunity-scriptableobjectsgame-ui-uxgodot-ui-controlaudio-designreferences/balancing.md