wave spawner, game phases, making game window larger
This commit is contained in:
+12
-6
@@ -5,7 +5,7 @@ import rl "vendor:raylib"
|
||||
Command_Kind :: enum {
|
||||
None,
|
||||
Place_Tower,
|
||||
Spawn_Test,
|
||||
Start_Wave,
|
||||
}
|
||||
|
||||
Command :: struct {
|
||||
@@ -15,14 +15,20 @@ Command :: struct {
|
||||
}
|
||||
|
||||
gather_commands :: proc(world: ^World) -> Command {
|
||||
if rl.IsMouseButtonPressed(.LEFT) {
|
||||
if world.phase == .Build && rl.IsKeyPressed(.N) {
|
||||
return Command{kind = .Start_Wave}
|
||||
}
|
||||
|
||||
if world.phase == .Build && rl.IsMouseButtonPressed(.LEFT) {
|
||||
mouse := rl.GetMousePosition()
|
||||
gx, gy := screen_to_grid(mouse.x, mouse.y)
|
||||
return Command{kind = .Place_Tower, gx = gx, gy = gy}
|
||||
}
|
||||
|
||||
if rl.IsKeyPressed(.SPACE) {
|
||||
return Command{kind = .Spawn_Test}
|
||||
if rl.IsMouseButtonPressed(.LEFT) {
|
||||
mouse := rl.GetMousePosition()
|
||||
gx, gy := screen_to_grid(mouse.x, mouse.y)
|
||||
return Command{kind = .Place_Tower, gx = gx, gy = gy}
|
||||
}
|
||||
|
||||
return Command{kind = .None}
|
||||
@@ -31,10 +37,10 @@ gather_commands :: proc(world: ^World) -> Command {
|
||||
execute_command :: proc(world: ^World, cmd: Command) {
|
||||
switch cmd.kind {
|
||||
case .None:
|
||||
case .Spawn_Test:
|
||||
spawn_group(world, 3)
|
||||
case .Place_Tower:
|
||||
try_place_tower(world, cmd.gx, cmd.gy, .Archer)
|
||||
case .Start_Wave:
|
||||
start_wave(world)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package game
|
||||
|
||||
MAP_W :: 16 // map width in tiles
|
||||
MAP_H :: 12 // map height in tiles
|
||||
MAP_W :: 30 // map width in tiles
|
||||
MAP_H :: 20 // map height in tiles
|
||||
TILE_SIZE :: 32 // size of tiles in pixels
|
||||
|
||||
SCREEN_W :: MAP_W * TILE_SIZE
|
||||
|
||||
@@ -2,6 +2,7 @@ package game
|
||||
|
||||
Event_Kind :: enum {
|
||||
Enemy_Killed,
|
||||
Wave_Survived,
|
||||
}
|
||||
|
||||
Event :: struct {
|
||||
@@ -18,6 +19,8 @@ process_events :: proc(world: ^World) {
|
||||
switch ev.kind {
|
||||
case .Enemy_Killed:
|
||||
world.gold += ev.gold_reward
|
||||
case .Wave_Survived:
|
||||
world.gold += ev.gold_reward
|
||||
}
|
||||
}
|
||||
clear(&world.events)
|
||||
|
||||
+6
-6
@@ -31,16 +31,16 @@ init_map :: proc(world_map: ^Map) {
|
||||
}
|
||||
}
|
||||
|
||||
for x in 1 ..< 13 {
|
||||
world_map.tiles[6][x] = .Path
|
||||
for x in 9 ..< 21 {
|
||||
world_map.tiles[10][x] = .Path
|
||||
}
|
||||
|
||||
for y in 7 ..< 8 {
|
||||
world_map.tiles[y][12] = .Path
|
||||
for y in 11 ..< 14 {
|
||||
world_map.tiles[y][20] = .Path
|
||||
}
|
||||
|
||||
for y in 4 ..< 9 {
|
||||
for x in 3 ..< 12 {
|
||||
for y in 7 ..< 15 {
|
||||
for x in 6 ..< 24 {
|
||||
if world_map.tiles[y][x] != .Path {
|
||||
world_map.tiles[y][x] = .Build
|
||||
}
|
||||
|
||||
+12
-3
@@ -35,8 +35,17 @@ render_world :: proc(world: ^World) {
|
||||
if (world.base_health == 0) {
|
||||
rl.DrawText("**GAME OVER**", 20, 20, 20, rl.RED)
|
||||
}
|
||||
rl.DrawText(fmt.ctprintf("Gold: %d", world.gold), 10, 10, 20, rl.BLACK) // Gold HUD
|
||||
rl.DrawText(fmt.ctprintf("Base HP: %d", world.base_health), 10, 32, 20, rl.BLACK) // HP HUD
|
||||
rl.DrawText(fmt.ctprintf("Enemies: %d", active_enemy_count(world)), 10, 54, 18, rl.DARKGRAY)
|
||||
|
||||
rl.DrawText(fmt.ctprintf("Gold: %d", world.gold), 10, 10, 22, rl.BLACK) // Gold HUD
|
||||
rl.DrawText(fmt.ctprintf("Base HP: %d", world.base_health), 10, 32, 22, rl.BLACK) // HP HUD
|
||||
rl.DrawText(fmt.ctprintf("Enemies: %d", active_enemy_count(world)), 10, 54, 22, rl.BLACK)
|
||||
rl.DrawText(fmt.ctprintf("Wave: %d / %d", world.wave, MAX_WAVES), 10, 76, 22, rl.BLACK)
|
||||
|
||||
switch world.phase {
|
||||
case .Build:
|
||||
rl.DrawText("Build - click towers, N = start wave", 10, 98, 22, rl.BLACK)
|
||||
case .Combat:
|
||||
rl.DrawText("Combat!", 10, 74, 22, rl.MAROON)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -19,7 +19,7 @@ Tower_Archetype :: struct {
|
||||
}
|
||||
|
||||
TOWER_ARCHETYPES: [Tower_Kind]Tower_Archetype = {
|
||||
.Archer = {kind = .Archer, range = 95, damage = 12, fire_rate = 0.45, cost = TOWER_COST},
|
||||
.Archer = {kind = .Archer, range = 20, damage = 12, fire_rate = 0.45, cost = TOWER_COST},
|
||||
}
|
||||
|
||||
get_archetype :: proc(kind: Tower_Kind) -> Tower_Archetype {
|
||||
@@ -27,6 +27,7 @@ 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
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package game
|
||||
|
||||
Game_Phase :: enum {
|
||||
Build,
|
||||
Combat,
|
||||
}
|
||||
|
||||
Wave_Spawner :: struct {
|
||||
enemies_to_spawn: int,
|
||||
spawn_timer: f32,
|
||||
spawn_interval: f32,
|
||||
}
|
||||
|
||||
start_wave :: proc(world: ^World) {
|
||||
if world.phase != .Build do return
|
||||
world.wave += 1
|
||||
world.phase = .Combat
|
||||
world.spawner = Wave_Spawner {
|
||||
enemies_to_spawn = 5 + world.wave * 2,
|
||||
spawn_timer = 0,
|
||||
spawn_interval = 0.55,
|
||||
}
|
||||
}
|
||||
|
||||
update_wave :: proc(world: ^World, dt: f32) {
|
||||
if world.phase != .Combat do return
|
||||
if world.spawner.enemies_to_spawn <= 0 do return
|
||||
if len(world.path) < 2 do return
|
||||
|
||||
world.spawner.spawn_timer -= dt
|
||||
if world.spawner.spawn_timer <= 0 {
|
||||
health := 15 + world.wave * 5
|
||||
speed := 55 + f32(world.wave) * 5
|
||||
spawn_enemy(world, health, speed)
|
||||
world.spawner.enemies_to_spawn -= 1
|
||||
world.spawner.spawn_timer = world.spawner.spawn_interval
|
||||
}
|
||||
}
|
||||
|
||||
wave_clear :: proc(world: ^World) -> bool {
|
||||
if world.spawner.enemies_to_spawn > 0 do return false
|
||||
return active_enemy_count(world) == 0
|
||||
}
|
||||
|
||||
update_phase :: proc(world: ^World) {
|
||||
if world.phase == .Combat && wave_clear(world) {
|
||||
world.phase = .Build
|
||||
push_event(world, .Wave_Survived, gold_reward = 25)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,16 @@ World :: struct {
|
||||
enemies: [MAX_ENEMIES]Enemy,
|
||||
towers: [dynamic]Tower,
|
||||
events: [dynamic]Event,
|
||||
phase: Game_Phase,
|
||||
wave: int,
|
||||
spawner: Wave_Spawner,
|
||||
}
|
||||
|
||||
init_world :: proc() -> World {
|
||||
world := World {
|
||||
gold = 100,
|
||||
base_health = 20,
|
||||
phase = .Build,
|
||||
}
|
||||
init_map(&world.world_map)
|
||||
build_path(&world.world_map, &world.path)
|
||||
@@ -27,8 +31,10 @@ update_world :: proc(world: ^World, dt: f32) {
|
||||
cmd := gather_commands(world)
|
||||
execute_command(world, cmd)
|
||||
|
||||
update_wave(world, dt)
|
||||
update_enemies(world, dt)
|
||||
update_towers(world, dt)
|
||||
update_phase(world)
|
||||
process_events(world)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user