1.44mb-gamejam

submission for the 1.44mb game jam - https://2pgarcade.com/contest-144mb.html
git clone git://brookjeynes.dev/bjeynes/1.44mb-gamejam.git
Log | Files | Refs

commit 410b751ad9501886166e35a73a400a597286fce2
parent b6efce7dc80d44096c058ba013768601f57b5953
Author: brookjeynes <me@brookjeynes.dev>
Date:   Sat,  1 Aug 2026 21:04:37 +1000

feat: add upgrades menu

Signed-off-by: brookjeynes <me@brookjeynes.dev>

Diffstat:
Msrc/main.zig | 102++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/state.zig | 4+++-
2 files changed, 104 insertions(+), 2 deletions(-)

diff --git a/src/main.zig b/src/main.zig @@ -8,6 +8,9 @@ const Player = @import("./player.zig"); const GameState = @import("./state.zig").GameState; const Timer = @import("./timer.zig"); const Button = @import("./ui.zig").Button; +const UpgradeId = @import("./upgrade.zig").UpgradeId; +const upgrade_meta = @import("./upgrade.zig").meta; +const upgrade_fields = @typeInfo(UpgradeId).@"enum".fields; const start_button = Button.new( .{ .x = 100, .y = 70 }, @@ -53,7 +56,104 @@ pub fn main() !void { game_state.reset(); } }, - .upgrade => {}, + .upgrade => { + raylib.BeginDrawing(); + defer raylib.EndDrawing(); + + raylib.ClearBackground(raylib.RAYWHITE); + + raylib.DrawText("upgrades", 20, 40, 30, raylib.BLACK); + raylib.DrawText( + raylib.TextFormat("points: %d", game_state.enemies_killed), + 20, + 90, + 20, + raylib.BLACK, + ); + raylib.DrawText( + raylib.TextFormat("last run: %0.1fs", game_state.time), + 20, + 120, + 18, + raylib.GRAY, + ); + + const row_size: raylib.Vector2 = .{ .x = 700, .y = 60 }; + const row_spacing: f32 = 80; + var row_position: raylib.Vector2 = .{ .x = 50, .y = 200 }; + + inline for (upgrade_fields) |field| { + const id: UpgradeId = @enumFromInt(field.value); + const meta = upgrade_meta[@intFromEnum(id)]; + + const level = game_state.upgrades.level(id); + const cost = game_state.upgrades.cost(id); + const buyable = !game_state.upgrades.maxed(id) and game_state.enemies_killed >= cost; + + const row = Button.new(row_size, row_position); + raylib.DrawRectangleV( + row.position, + row.size, + if (buyable) raylib.BLACK else raylib.GRAY, + ); + raylib.DrawText( + meta.name.ptr, + @intFromFloat(row.position.x + 20), + @intFromFloat(row.position.y + row.size.y / 2 - 10), + 20, + raylib.WHITE, + ); + + if (game_state.upgrades.maxed(id)) { + raylib.DrawText( + "MAX", + @intFromFloat(row.position.x + row.size.x - 120), + @intFromFloat(row.position.y + row.size.y / 2 - 10), + 18, + raylib.WHITE, + ); + } else { + raylib.DrawText( + raylib.TextFormat("lvl %d/%d cost %d", level, meta.max_level, cost), + @intFromFloat(row.position.x + row.size.x - 300), + @intFromFloat(row.position.y + row.size.y / 2 - 10), + 18, + raylib.WHITE, + ); + } + + if (buyable and row.clicked(raylib.GetMousePosition())) { + game_state.enemies_killed -= cost; + _ = game_state.upgrades.upgrade(id); + } + + row_position.y += row_spacing; + } + + const continue_button = Button.new( + .{ .x = 300, .y = 60 }, + .{ + .x = (constants.screen_width / 2) - 150, + .y = row_position.y + 60, + }, + ); + raylib.DrawRectangleV( + continue_button.position, + continue_button.size, + raylib.BLACK, + ); + raylib.DrawText( + "continue", + @intFromFloat(continue_button.position.x + continue_button.size.x / 2 - 30), + @intFromFloat(continue_button.position.y + continue_button.size.y / 2 - 10), + 20, + raylib.WHITE, + ); + + if (continue_button.clicked(raylib.GetMousePosition())) { + game_state.reset(); + } + }, .gameplay => { // -- tick for (0..game_state.enemy_count) |idx| { diff --git a/src/state.zig b/src/state.zig @@ -23,6 +23,7 @@ pub const GameState = struct { player: Player, upgrades: Upgrades, + enemies_killed: u16 = 0, enemies: [constants.max_enemies]Entity, enemy_count: u8, @@ -96,7 +97,7 @@ pub const GameState = struct { self.player.tick(); if (self.player.health <= 0) { - self.screen = .title; + self.screen = .upgrade; } for (0..self.enemy_count) |i| { @@ -165,6 +166,7 @@ pub const GameState = struct { if (is_collision) { self.player.bullet_pool.despawn(player_bullet_idx); self.despawn_enemy(enemy_idx); + self.enemies_killed += 1; continue :lbl; } }