supporting different size towers

This commit is contained in:
2026-06-15 01:05:11 -07:00
parent 50882df786
commit 6df2cbf7de
+98 -21
View File
@@ -3,9 +3,11 @@ package game
import rl "vendor:raylib"
Tower :: struct {
position: Vec2,
kind: Tower_Kind,
cooldown: f32,
position: Vec2,
kind: Tower_Kind,
cooldown: f32,
anchor_gx: int,
anchor_gy: int,
}
Tower_Kind :: enum {
@@ -13,15 +15,78 @@ Tower_Kind :: enum {
}
Tower_Archetype :: struct {
kind: Tower_Kind,
range: f32,
damage: int,
fire_rate: f32,
cost: int,
kind: Tower_Kind,
range: f32,
damage: int,
fire_rate: f32,
cost: int,
footprint_w: int, // 1 column wide
footprint_h: int, // two rows tall
}
TOWER_ARCHETYPES: [Tower_Kind]Tower_Archetype = {
.Archer = {kind = .Archer, range = 50, damage = 12, fire_rate = 0.45, cost = TOWER_COST},
.Archer = {
kind = .Archer,
range = 50,
damage = 12,
fire_rate = 0.45,
cost = TOWER_COST,
footprint_w = 1,
footprint_h = 2,
},
}
rects_overlap :: proc(
left_a, top_a, width_a, height_a: int,
left_b, top_b, width_b, height_b: int,
) -> bool {
return(
left_a < left_b + width_b &&
left_a + width_a > left_b &&
top_a < top_b + height_b &&
top_a + height_a > top_b \
)
}
footprint_center :: proc(gx, gy, footprint_w, footprint_h: int) -> Vec2 {
return Vec2 {
f32(gx * TILE_SIZE + (footprint_w * TILE_SIZE) / 2),
f32(gy * TILE_SIZE + (footprint_h + TILE_SIZE) / 2),
}
}
footprint_fits_map :: proc(world_map: ^Map, gx, gy, footprint_w, footprint_h: int) -> bool {
if gx < 0 || gy < 0 do return false
if gx + footprint_w > MAP_W do return false
if gy + footprint_h > MAP_H do return false
for row in gy ..< gy + footprint_h {
for column in gx ..< gx + footprint_w {
if !can_build_at(world_map, column, row) do return false
}
}
return true
}
footprint_blocked :: proc(world: ^World, gx, gy, footprint_w, footprint_h: int) -> bool {
for placed_tower in world.towers {
archetype := get_archetype(placed_tower.kind)
if rects_overlap(
gx,
gy,
footprint_w,
footprint_h,
placed_tower.anchor_gx,
placed_tower.anchor_gy,
archetype.footprint_w,
archetype.footprint_h,
) {
return true
}
}
return false
}
get_archetype :: proc(kind: Tower_Kind) -> Tower_Archetype {
@@ -30,17 +95,26 @@ get_archetype :: proc(kind: Tower_Kind) -> Tower_Archetype {
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
}
arch := get_archetype(kind)
footprint_w := arch.footprint_w
footprint_h := arch.footprint_h
if !footprint_fits_map(&world.world_map, gx, gy, footprint_w, footprint_h) do return false
if footprint_blocked(world, gx, gy, footprint_w, footprint_h) do return false
if world.gold < arch.cost do return false
world.gold -= arch.cost
append(&world.towers, Tower{position = pos, kind = kind, cooldown = 0})
append(
&world.towers,
Tower {
position = footprint_center(gx, gy, footprint_w, footprint_h),
anchor_gx = gx,
anchor_gy = gy,
kind = kind,
cooldown = 0,
},
)
return true
}
@@ -85,11 +159,14 @@ update_towers :: proc(world: ^World, dt: f32) {
render_towers :: proc(world: ^World) {
for t in world.towers {
archetype := get_archetype(t.kind)
pixel_width := f32(archetype.footprint_w * TILE_SIZE)
pixel_height := f32(archetype.footprint_h * TILE_SIZE)
rl.DrawRectangle(
i32(t.position.x - 14),
i32(t.position.y - 14),
28,
28,
i32(t.position.x - pixel_width * 0.5),
i32(t.position.y - pixel_height * 0.5),
i32(pixel_width),
i32(pixel_height),
rl.Color{255, 203, 0, 255},
)
}