diff --git a/game/commands.odin b/game/commands.odin index a07704e..e906498 100644 --- a/game/commands.odin +++ b/game/commands.odin @@ -20,6 +20,7 @@ gather_commands :: proc(world: ^World) -> Command { if rl.IsKeyPressed(.ONE) do world.selected_tower = .Archer if rl.IsKeyPressed(.TWO) do world.selected_tower = .Cannon + if rl.IsKeyPressed(.THREE) do world.selected_tower = .Ice if world.phase == .Build && rl.IsKeyPressed(.N) { return Command{kind = .Start_Wave} } diff --git a/game/constants.odin b/game/constants.odin index f0d4301..2cdaa03 100644 --- a/game/constants.odin +++ b/game/constants.odin @@ -38,3 +38,6 @@ CONTROLS_SHOP_IDLE :: rl.Color{45, 75, 45, 255} CONTROL_SHOP_SELECTED :: rl.Color{70, 110, 70, 255} CONTROLS_SHOP_HOVER :: rl.Color{90, 130, 90, 255} +ICE_SLOW_DURATION :: 2.5 +ICE_SLOW_FACTOR :: 0.5 + diff --git a/game/enemy.odin b/game/enemy.odin index 0e90100..54be1a2 100644 --- a/game/enemy.odin +++ b/game/enemy.odin @@ -1,6 +1,7 @@ package game import "core:fmt" +import "core:sys/posix" import rl "vendor:raylib" Enemy :: struct { @@ -9,7 +10,8 @@ Enemy :: struct { max_health: int, active: bool, path_index: int, - speed: f32, + base_speed: f32, + slow_timer: f32, } acquire_enemy :: proc(world: ^World) -> ^Enemy { @@ -33,7 +35,8 @@ spawn_enemy :: proc(world: ^World, health: int, speed: f32) { position = world.path[0], health = health, max_health = health, - speed = speed, + base_speed = speed, + slow_timer = 0, path_index = 1, active = true, } @@ -59,7 +62,12 @@ update_enemies :: proc(world: ^World, dt: f32) { } target := world.path[e.path_index] - move_toward(&e.position, target, e.speed, dt) + move_speed := e.base_speed + if e.slow_timer > 0 { + move_speed *= ICE_SLOW_FACTOR + e.slow_timer -= dt + } + move_toward(&e.position, target, move_speed, dt) dx := target.x - e.position.x dy := target.y - e.position.y @@ -83,6 +91,9 @@ render_enemies :: proc(world: ^World) { e := world.enemies[i] if !e.active do continue rl.DrawCircle(i32(e.position.x), i32(e.position.y), 11, rl.MAROON) + if e.slow_timer > 0 { + rl.DrawCircleLines(i32(e.position.x), i32(e.position.y), 14, rl.SKYBLUE) + } rl.DrawText( fmt.ctprintf("%d", e.health), i32(e.position.x) - 4, diff --git a/game/tower.odin b/game/tower.odin index 4471b5a..ada77dc 100644 --- a/game/tower.odin +++ b/game/tower.odin @@ -13,6 +13,7 @@ Tower :: struct { Tower_Kind :: enum { Archer, Cannon, + Ice, } Tower_Archetype :: struct { @@ -44,6 +45,15 @@ TOWER_ARCHETYPES: [Tower_Kind]Tower_Archetype = { footprint_w = 2, footprint_h = 2, }, + .Ice = { + kind = .Ice, + range = 85, + damage = 6, + fire_rate = 0.55, + cost = 65, + footprint_w = 1, + footprint_h = 1, + }, } rects_overlap :: proc( @@ -166,6 +176,10 @@ update_towers :: proc(world: ^World, dt: f32) { if target := enemy_at_slot(world, slot); target != nil { apply_tower_hit(world, target, arch.damage) } + case .Ice: + if target := enemy_at_slot(world, slot); target != nil { + apply_ice_hit(world, target, arch.damage) + } } t.cooldown = arch.fire_rate } @@ -179,6 +193,11 @@ apply_tower_hit :: proc(world: ^World, target: ^Enemy, damage: int) { } } +apply_ice_hit :: proc(world: ^World, target: ^Enemy, damage: int) { + apply_tower_hit(world, target, damage) + if target.active do target.slow_timer = ICE_SLOW_DURATION +} + enemy_at_slot :: proc(world: ^World, slot: int) -> ^Enemy { if slot < 0 || slot >= MAX_ENEMIES do return nil