add event queue, tower archetypes, and enemy damage. no projectiles yet
This commit is contained in:
+1
-1
@@ -34,7 +34,7 @@ execute_command :: proc(world: ^World, cmd: Command) {
|
||||
case .Spawn_Test:
|
||||
spawn_group(world, 3)
|
||||
case .Place_Tower:
|
||||
try_place_tower(world, cmd.gx, cmd.gy)
|
||||
try_place_tower(world, cmd.gx, cmd.gy, .Archer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package game
|
||||
|
||||
Event_Kind :: enum {
|
||||
Enemy_Killed,
|
||||
}
|
||||
|
||||
Event :: struct {
|
||||
kind: Event_Kind,
|
||||
gold_reward: int,
|
||||
}
|
||||
|
||||
push_event :: proc(world: ^World, kind: Event_Kind, gold_reward: int = 0) {
|
||||
append(&world.events, Event{kind = kind, gold_reward = gold_reward})
|
||||
}
|
||||
|
||||
process_events :: proc(world: ^World) {
|
||||
for ev in world.events {
|
||||
switch ev.kind {
|
||||
case .Enemy_Killed:
|
||||
world.gold += ev.gold_reward
|
||||
}
|
||||
}
|
||||
clear(&world.events)
|
||||
}
|
||||
|
||||
+66
-3
@@ -2,9 +2,32 @@ package game
|
||||
|
||||
Tower :: struct {
|
||||
position: Vec2,
|
||||
kind: Tower_Kind,
|
||||
cooldown: f32,
|
||||
}
|
||||
|
||||
try_place_tower :: proc(world: ^World, gx, gy: int) -> bool {
|
||||
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 = 95, 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 {
|
||||
arch := get_archetype(kind)
|
||||
if !can_build_at(&world.world_map, gx, gy) do return false
|
||||
if world.gold < TOWER_COST do return false
|
||||
|
||||
@@ -13,8 +36,48 @@ try_place_tower :: proc(world: ^World, gx, gy: int) -> bool {
|
||||
if distance(t.position, pos) < 1 do return false
|
||||
}
|
||||
|
||||
world.gold -= TOWER_COST
|
||||
append(&world.towers, Tower{position = pos})
|
||||
world.gold -= arch.cost
|
||||
append(&world.towers, Tower{position = pos, kind = kind, cooldown = 0})
|
||||
return true
|
||||
}
|
||||
|
||||
find_target :: proc(tower: Tower, world: ^World) -> ^Enemy {
|
||||
arch := get_archetype(tower.kind)
|
||||
best: ^Enemy = nil
|
||||
best_dist: f32 = 999999
|
||||
|
||||
for i in 0 ..< MAX_ENEMIES {
|
||||
e := &world.enemies[i]
|
||||
|
||||
if !e.active do continue
|
||||
|
||||
d := distance(tower.position, e.position)
|
||||
if d <= arch.range && d < best_dist {
|
||||
best = e
|
||||
best_dist = d
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
target := find_target(t^, world)
|
||||
if target == nil do continue
|
||||
|
||||
arch := get_archetype(t.kind)
|
||||
target.health -= arch.damage
|
||||
t.cooldown = arch.fire_rate
|
||||
|
||||
if target.health <= 0 {
|
||||
target.active = false
|
||||
push_event(world, .Enemy_Killed, gold_reward = 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ World :: struct {
|
||||
path: [dynamic]Vec2,
|
||||
enemies: [MAX_ENEMIES]Enemy,
|
||||
towers: [dynamic]Tower,
|
||||
events: [dynamic]Event,
|
||||
}
|
||||
|
||||
init_world :: proc() -> World {
|
||||
@@ -27,5 +28,7 @@ update_world :: proc(world: ^World, dt: f32) {
|
||||
execute_command(world, cmd)
|
||||
|
||||
update_enemies(world, dt)
|
||||
update_towers(world, dt)
|
||||
process_events(world)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user