From 433ac4152ba4732e44e8c17d29ac02a343ea8ad2 Mon Sep 17 00:00:00 2001 From: codegirl-007 Date: Fri, 19 Jun 2026 01:48:48 -0700 Subject: [PATCH] first go at a control panel, not fancy --- game/app.odin | 1 + game/commands.odin | 8 +----- game/constants.odin | 10 +++++-- game/controls.odin | 69 +++++++++++++++++++++++++++++++++++++++++++++ game/overlay.odin | 26 ----------------- game/world.odin | 30 +++++++++++--------- 6 files changed, 95 insertions(+), 49 deletions(-) create mode 100644 game/controls.odin diff --git a/game/app.odin b/game/app.odin index 04da9d3..89df930 100644 --- a/game/app.odin +++ b/game/app.odin @@ -19,6 +19,7 @@ run :: proc() { render_world(&world) render_overlay(&world) + render_controls(&world) rl.EndDrawing() } diff --git a/game/commands.odin b/game/commands.odin index fb021e2..c4dde27 100644 --- a/game/commands.odin +++ b/game/commands.odin @@ -15,7 +15,7 @@ Command :: struct { } gather_commands :: proc(world: ^World) -> Command { - ui_cmd := overlay_ui_command(world) + ui_cmd := poll_controls_command(world) if ui_cmd.kind != .None do return ui_cmd if world.phase == .Build && rl.IsKeyPressed(.N) { @@ -28,12 +28,6 @@ gather_commands :: proc(world: ^World) -> Command { return Command{kind = .Place_Tower, gx = gx, gy = gy} } - 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} } diff --git a/game/constants.odin b/game/constants.odin index a433b69..1a4f41b 100644 --- a/game/constants.odin +++ b/game/constants.odin @@ -26,6 +26,12 @@ OVERLAY_BAR_COLOR :: rl.Color{20, 24, 20, 200} OVERLAY_GOLD_COLOR :: rl.Color{255, 215, 80, 255} OVERLAY_TEXT_COLOR :: rl.Color{240, 240, 230, 255} -OVERLAY_BUTTON_COLOR :: rl.Color{60, 120, 60, 255} -OVERLAY_BUTTON_HOVER :: rl.Color{80, 150, 80, 255} +CONTROL_BAR_H :: 40 +CONTROL_BAR_BG :: rl.Color{30, 55, 30, 220} +CONTROL_BUTTON_COLOR :: rl.Color{60, 120, 60, 255} +CONTROL_BUTTON_HOVER :: rl.Color{60, 150, 60, 255} + +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} diff --git a/game/controls.odin b/game/controls.odin new file mode 100644 index 0000000..ea2f69f --- /dev/null +++ b/game/controls.odin @@ -0,0 +1,69 @@ +package game + +import "core:fmt" +import rl "vendor:raylib" + +bottom_bar_y :: proc() -> i32 { + return SCREEN_H - CONTROL_BAR_H +} + +build_controls_layout :: proc() -> (archer, start_wave_btn: rl.Rectangle) { + bar_y := f32(bottom_bar_y()) + arch_w: f32 = 120 + wave_w: f32 = 110 + gap: f32 = 12 + + x := f32((SCREEN_W - int(arch_w + gap + wave_w)) / 2) + archer = {x, bar_y + 8, arch_w, 24} + start_wave_btn = {x + arch_w + gap, bar_y + 8, wave_w, 24} + return +} + +poll_controls_command :: proc(world: ^World) -> Command { + if world.phase != .Build do return Command{kind = .None} + + mouse := rl.GetMousePosition() + if rl.IsMouseButtonPressed(.LEFT) { + archer, start_wave := build_controls_layout() + if rl.CheckCollisionPointRec(mouse, archer) { + world.selected_tower = .Archer + } + if rl.CheckCollisionPointRec(mouse, start_wave) { + return Command{kind = .Start_Wave} + } + } + + return Command{kind = .None} +} + +render_controls :: proc(world: ^World) { + if world.phase != .Build do return + + bar_y := bottom_bar_y() + rl.DrawRectangle(0, bar_y, SCREEN_W, CONTROL_BAR_H, CONTROL_BAR_BG) + + arch := get_archetype(.Archer) + archer, start_wave_btn := build_controls_layout() + mouse := rl.GetMousePosition() + + arch_bg := CONTROLS_SHOP_IDLE + if world.selected_tower == .Archer do arch_bg = CONTROL_SHOP_SELECTED + if rl.CheckCollisionPointRec(mouse, archer) do arch_bg = CONTROL_BUTTON_HOVER + rl.DrawRectangleRec(archer, arch_bg) + label := fmt.ctprintf("Archer - %dg", arch.cost) + rl.DrawText(label, i32(archer.x) + 6, i32(archer.y) + 4, 14, OVERLAY_TEXT_COLOR) + + + wave_bg := CONTROL_BUTTON_COLOR + if rl.CheckCollisionPointRec(mouse, start_wave_btn) do wave_bg = CONTROLS_SHOP_HOVER + rl.DrawRectangleRec(start_wave_btn, wave_bg) + + rl.DrawText( + "Start Wave", + i32(start_wave_btn.x) + 8, + i32(start_wave_btn.y) + 3, + 16, + OVERLAY_TEXT_COLOR, + ) +} + diff --git a/game/overlay.odin b/game/overlay.odin index dcce60f..20cc9a9 100644 --- a/game/overlay.odin +++ b/game/overlay.odin @@ -18,31 +18,5 @@ render_overlay :: proc(world: ^World) { hp := fmt.ctprintf("Health: %d", world.base_health) rl.DrawText(hp, x, y, font_size, OVERLAY_TEXT_COLOR) - - if world.phase == .Build { - btn := start_wave_button_rect() - mouse := rl.GetMousePosition() - hovered := rl.CheckCollisionPointRec(mouse, btn) - bg := hovered ? OVERLAY_BUTTON_HOVER : OVERLAY_BUTTON_COLOR - rl.DrawRectangleRec(btn, bg) - rl.DrawText("Start Wave", i32(btn.x) + 8, i32(btn.y) + 3, 16, OVERLAY_TEXT_COLOR) - } -} - -start_wave_button_rect :: proc() -> rl.Rectangle { - return {x = f32(SCREEN_W - 120), y = 3, width = 110, height = 22} -} - -overlay_ui_command :: proc(world: ^World) -> Command { - if world.phase != .Build do return Command{kind = .None} - - mouse := rl.GetMousePosition() - btn := start_wave_button_rect() - - if rl.CheckCollisionPointRec(mouse, btn) && rl.IsMouseButtonPressed(.LEFT) { - return Command{kind = .Start_Wave} - } - - return Command{kind = .None} } diff --git a/game/world.odin b/game/world.odin index 1151e55..fec5502 100644 --- a/game/world.odin +++ b/game/world.odin @@ -1,24 +1,26 @@ package game World :: struct { - gold: int, - base_health: int, - world_map: Map, - path: [dynamic]Vec2, - enemies: [MAX_ENEMIES]Enemy, - towers: [dynamic]Tower, - events: [dynamic]Event, - phase: Game_Phase, - wave: int, - spawner: Wave_Spawner, - projectiles: [MAX_PROJECTILES]Projectile, + gold: int, + base_health: int, + world_map: Map, + path: [dynamic]Vec2, + enemies: [MAX_ENEMIES]Enemy, + towers: [dynamic]Tower, + events: [dynamic]Event, + phase: Game_Phase, + wave: int, + spawner: Wave_Spawner, + projectiles: [MAX_PROJECTILES]Projectile, + selected_tower: Tower_Kind, } init_world :: proc() -> World { world := World { - gold = 100, - base_health = 20, - phase = .Build, + gold = 100, + base_health = 20, + phase = .Build, + selected_tower = .Archer, } init_map(&world.world_map) build_path(&world.world_map, &world.path)