113 lines
2.4 KiB
Odin
113 lines
2.4 KiB
Odin
package game
|
|
|
|
Game_Phase :: enum {
|
|
Build,
|
|
Combat,
|
|
Game_Over,
|
|
Victory,
|
|
}
|
|
|
|
Wave_Spawner :: struct {
|
|
spawn_timer: f32,
|
|
spawn_interval: f32,
|
|
recipe: [dynamic]Wave_Entry,
|
|
recipe_index: int,
|
|
entry_remaining: int,
|
|
}
|
|
|
|
start_wave :: proc(world: ^World) {
|
|
if world.phase != .Build do return
|
|
world.wave.current_wave += 1
|
|
world.phase = .Combat
|
|
delete(world.wave.spawner.recipe)
|
|
world.wave.spawner = Wave_Spawner {
|
|
spawn_timer = 0,
|
|
spawn_interval = 0.55,
|
|
recipe = build_wave_recipe(world.wave.current_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.wave.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.wave.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
|
|
s := &world.wave.spawner
|
|
if s.entry_remaining <= 0 && s.recipe_index >= len(s.recipe) do return
|
|
|
|
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
|
|
}
|
|
|
|
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 && clear_wave(world) {
|
|
world.phase = .Build
|
|
push_event(world, .Wave_Survived, gold_reward = 25)
|
|
}
|
|
}
|
|
|
|
check_end :: proc(world: ^World) {
|
|
if world.base_health <= 0 {
|
|
world.phase = .Game_Over
|
|
}
|
|
|
|
if world.wave.current_wave >= MAX_WAVES && world.phase == .Build && clear_wave(world) {
|
|
world.phase = .Victory
|
|
}
|
|
}
|
|
|