Add different enemy types (Runner)
This commit is contained in:
+47
-11
@@ -12,8 +12,41 @@ Enemy :: struct {
|
||||
path_index: int,
|
||||
base_speed: f32,
|
||||
slow_timer: f32,
|
||||
kind: Enemy_Kind,
|
||||
}
|
||||
|
||||
Enemy_Kind :: enum {
|
||||
Grunt,
|
||||
Runner,
|
||||
}
|
||||
|
||||
Enemy_Archetype :: struct {
|
||||
kind: Enemy_Kind,
|
||||
health: int,
|
||||
speed: f32,
|
||||
color: rl.Color,
|
||||
}
|
||||
|
||||
get_enemy_archetype :: proc(kind: Enemy_Kind, wave: int) -> Enemy_Archetype {
|
||||
switch kind {
|
||||
case .Grunt:
|
||||
return {
|
||||
kind = .Grunt,
|
||||
health = 15 + wave * 5,
|
||||
speed = 55 + f32(wave) * 5,
|
||||
color = rl.MAROON,
|
||||
}
|
||||
case .Runner:
|
||||
return {
|
||||
kind = .Runner,
|
||||
health = 10 + wave * 2,
|
||||
speed = 95 + f32(wave) * 3,
|
||||
color = rl.ORANGE,
|
||||
}
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
acquire_enemy :: proc(world: ^World) -> ^Enemy {
|
||||
// create an object pool with fixed slots to reuse instead of allocate/free every spawn
|
||||
for i in 0 ..< MAX_ENEMIES {
|
||||
@@ -25,29 +58,25 @@ acquire_enemy :: proc(world: ^World) -> ^Enemy {
|
||||
return nil
|
||||
}
|
||||
|
||||
spawn_enemy :: proc(world: ^World, health: int, speed: f32) {
|
||||
spawn_enemy :: proc(world: ^World, kind: Enemy_Kind) {
|
||||
if len(world.path) == 0 do return // don't spawn enemies if no paths exist
|
||||
|
||||
e := acquire_enemy(world) // grab a free slot
|
||||
if e == nil do return // if there are no slots, skil spawning
|
||||
|
||||
arch := get_enemy_archetype(kind, world.wave)
|
||||
e^ = Enemy {
|
||||
position = world.path[0],
|
||||
health = health,
|
||||
max_health = health,
|
||||
base_speed = speed,
|
||||
health = arch.health,
|
||||
max_health = arch.health,
|
||||
base_speed = arch.speed,
|
||||
slow_timer = 0,
|
||||
path_index = 1,
|
||||
kind = kind,
|
||||
active = true,
|
||||
}
|
||||
}
|
||||
|
||||
spawn_group :: proc(world: ^World, count: int) {
|
||||
for _ in 0 ..< count {
|
||||
spawn_enemy(world, 20, 60)
|
||||
}
|
||||
}
|
||||
|
||||
update_enemies :: proc(world: ^World, dt: f32) {
|
||||
for i in 0 ..< MAX_ENEMIES {
|
||||
e := &world.enemies[i]
|
||||
@@ -90,7 +119,14 @@ render_enemies :: proc(world: ^World) {
|
||||
for i in 0 ..< MAX_ENEMIES {
|
||||
e := world.enemies[i]
|
||||
if !e.active do continue
|
||||
rl.DrawCircle(i32(e.position.x), i32(e.position.y), 11, rl.MAROON)
|
||||
color := rl.MAROON
|
||||
switch e.kind {
|
||||
case .Grunt:
|
||||
color = rl.MAROON
|
||||
case .Runner:
|
||||
color = rl.ORANGE
|
||||
}
|
||||
rl.DrawCircle(i32(e.position.x), i32(e.position.y), 11, color)
|
||||
if e.slow_timer > 0 {
|
||||
rl.DrawCircleLines(i32(e.position.x), i32(e.position.y), 14, rl.SKYBLUE)
|
||||
}
|
||||
|
||||
+5
-1
@@ -11,6 +11,7 @@ Wave_Spawner :: struct {
|
||||
enemies_to_spawn: int,
|
||||
spawn_timer: f32,
|
||||
spawn_interval: f32,
|
||||
spawn_count: int,
|
||||
}
|
||||
|
||||
start_wave :: proc(world: ^World) {
|
||||
@@ -30,10 +31,13 @@ update_wave :: proc(world: ^World, dt: f32) {
|
||||
if len(world.path) < 2 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, health, speed)
|
||||
spawn_enemy(world, kind)
|
||||
world.spawner.spawn_count += 1
|
||||
world.spawner.enemies_to_spawn -= 1
|
||||
world.spawner.spawn_timer = world.spawner.spawn_interval
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user