wave recipes + tanks

This commit is contained in:
2026-06-24 20:28:02 -07:00
parent 4bb3e710c1
commit d6ee5abb01
2 changed files with 83 additions and 26 deletions
+69 -25
View File
@@ -8,10 +8,11 @@ Game_Phase :: enum {
}
Wave_Spawner :: struct {
enemies_to_spawn: int,
spawn_timer: f32,
spawn_interval: f32,
spawn_count: int,
spawn_timer: f32,
spawn_interval: f32,
recipe: [dynamic]Wave_Entry,
recipe_index: int,
entry_remaining: int,
}
start_wave :: proc(world: ^World) {
@@ -19,37 +20,80 @@ start_wave :: proc(world: ^World) {
world.wave += 1
world.phase = .Combat
world.spawner = Wave_Spawner {
enemies_to_spawn = 5 + world.wave * 2,
spawn_timer = 0,
spawn_interval = 0.55,
spawn_timer = 0,
spawn_interval = 0.55,
recipe = build_wave_recipe(world.wave),
recipe_index = 0,
entry_remaining = 0,
}
load_next_recipe_entry(world)
}
Wave_Entry :: struct {
kind: Enemy_Kind,
count: int,
}
build_wave_recipe :: proc(wave: int) -> [dynamic]Wave_Entry {
recipe: [dynamic]Wave_Entry
switch wave {
case 1:
append(&recipe, Wave_Entry{.Grunt, 6})
case 2:
append(&recipe, Wave_Entry{.Grunt, 4})
append(&recipe, Wave_Entry{.Runner, 2})
case:
grunt := 3 + wave
runners := wave / 2
tanks := wave / 3
append(&recipe, Wave_Entry{.Grunt, grunt})
if runners > 0 do append(&recipe, Wave_Entry{.Runner, runners})
if tanks > 0 do append(&recipe, Wave_Entry{.Tank, tanks})
}
return recipe
}
load_next_recipe_entry :: proc(world: ^World) {
s := &world.spawner
if s.recipe_index >= len(s.recipe) {
s.entry_remaining = 0
return
}
entry := s.recipe[s.recipe_index]
s.entry_remaining = entry.count
}
clear_wave :: proc(world: ^World) -> bool {
s := world.spawner
if s.recipe_index < len(s.recipe) do return false
if s.entry_remaining > 0 do return false
return active_enemy_count(world) == 0
}
update_wave :: proc(world: ^World, dt: f32) {
if world.phase != .Combat do return
if world.spawner.enemies_to_spawn <= 0 do return
if len(world.path) < 2 do return
s := &world.spawner
if s.entry_remaining <= 0 && s.recipe_index >= len(s.recipe) do return
world.spawner.spawn_timer -= dt
kind := Enemy_Kind.Grunt
if world.spawner.spawn_count % 3 == 2 do kind = .Runner
if world.spawner.spawn_timer <= 0 {
health := 15 + world.wave * 5
speed := 55 + f32(world.wave) * 5
spawn_enemy(world, kind)
world.spawner.spawn_count += 1
world.spawner.enemies_to_spawn -= 1
world.spawner.spawn_timer = world.spawner.spawn_interval
s.spawn_timer -= dt
if s.spawn_timer > 0 do return
if s.entry_remaining <= 0 {
s.recipe_index += 1
load_next_recipe_entry(world)
if s.entry_remaining <= 0 do return
}
}
wave_clear :: proc(world: ^World) -> bool {
if world.spawner.enemies_to_spawn > 0 do return false
return active_enemy_count(world) == 0
kind := s.recipe[s.recipe_index].kind
spawn_enemy(world, kind)
s.entry_remaining -= 1
s.spawn_timer = s.spawn_interval
}
update_phase :: proc(world: ^World) {
if world.phase == .Combat && wave_clear(world) {
if world.phase == .Combat && clear_wave(world) {
world.phase = .Build
push_event(world, .Wave_Survived, gold_reward = 25)
}
@@ -60,7 +104,7 @@ check_end :: proc(world: ^World) {
world.phase = .Game_Over
}
if world.wave >= MAX_WAVES && world.phase == .Build && wave_clear(world) {
if world.wave >= MAX_WAVES && world.phase == .Build && clear_wave(world) {
world.phase = .Victory
}
}