Files
tower-defense-prototype/game/tower.odin
T
2026-06-14 01:11:51 -07:00

98 lines
2.0 KiB
Odin

package game
import rl "vendor:raylib"
Tower :: struct {
position: Vec2,
kind: Tower_Kind,
cooldown: f32,
}
Tower_Kind :: enum {
Archer,
}
Tower_Archetype :: struct {
kind: Tower_Kind,
range: f32,
damage: int,
fire_rate: f32,
cost: int,
}
TOWER_ARCHETYPES: [Tower_Kind]Tower_Archetype = {
.Archer = {kind = .Archer, range = 50, damage = 12, fire_rate = 0.45, cost = TOWER_COST},
}
get_archetype :: proc(kind: Tower_Kind) -> Tower_Archetype {
return TOWER_ARCHETYPES[kind]
}
try_place_tower :: proc(world: ^World, gx, gy: int, kind: Tower_Kind) -> bool {
if world.phase != .Build do return false
arch := get_archetype(kind)
if !can_build_at(&world.world_map, gx, gy) do return false
if world.gold < TOWER_COST do return false
pos := grid_to_center(gx, gy)
for t in world.towers {
if distance(t.position, pos) < 1 do return false
}
world.gold -= arch.cost
append(&world.towers, Tower{position = pos, kind = kind, cooldown = 0})
return true
}
find_target_slot :: proc(tower: Tower, world: ^World) -> int {
arch := get_archetype(tower.kind)
best_slot: int = -1
best_dist: f32 = 999999
for i in 0 ..< MAX_ENEMIES {
e := &world.enemies[i]
if !e.active do continue
if e.path_index >= len(world.path) do continue
d := distance(tower.position, e.position)
if d <= arch.range && d < best_dist {
best_slot = i
best_dist = d
}
}
return best_slot
}
update_towers :: proc(world: ^World, dt: f32) {
for i in 0 ..< len(world.towers) {
t := &world.towers[i]
t.cooldown -= dt
if t.cooldown > 0 do continue
slot := find_target_slot(t^, world)
if slot < 0 do continue
arch := get_archetype(t.kind)
switch t.kind {
case .Archer:
spawn_projectile(world, t.position, slot, arch.damage)
t.cooldown = arch.fire_rate
}
}
}
render_towers :: proc(world: ^World) {
for t in world.towers {
rl.DrawRectangle(
i32(t.position.x - 14),
i32(t.position.y - 14),
28,
28,
rl.Color{255, 203, 0, 255},
)
}
}