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 7e3fb669f48770a55723c80e0302b661320cf331
parent a0e37348df914caae559bcdcf0ae385faa74e955
Author: brookjeynes <me@brookjeynes.dev>
Date:   Wed, 29 Jul 2026 12:39:32 +1000

feat: player shoots bullets

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

Diffstat:
Asrc/bullet.zig | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.zig | 44+++++++++++++++++++++++++++++++++++---------
Asrc/timer.zig | 15+++++++++++++++
3 files changed, 111 insertions(+), 9 deletions(-)

diff --git a/src/bullet.zig b/src/bullet.zig @@ -0,0 +1,61 @@ +const std = @import("std"); +const raylib = @import("raylib"); +const Timer = @import("./timer.zig").Timer; + +const speed: f16 = 300.0; +const radius: f16 = 10.0; +const spawn_cooldown: f16 = 0.4; + +pub const Bullet = struct { + position: raylib.Vector2, + direction: raylib.Vector2, + color: raylib.Color, +}; + +pub const Pool = struct { + bullets: std.ArrayList(Bullet) = .empty, + fire_timer: Timer = .{ .duration = spawn_cooldown }, + + pub fn tick(self: *Pool) bool { + return self.fire_timer.tick(raylib.GetFrameTime()); + } + + pub fn spawn( + self: *Pool, + allocator: std.mem.Allocator, + position: raylib.Vector2, + direction: raylib.Vector2, + ) !void { + try self.bullets.append(allocator, .{ + .position = position, + .direction = direction, + .color = raylib.MAROON, + }); + } + + pub fn render(self: *Pool, screen_size: raylib.Vector2) void { + const delta = raylib.GetFrameTime(); + + var i: usize = 0; + while (i < self.bullets.items.len) { + var bullet = &self.bullets.items[i]; + bullet.position.x += bullet.direction.x * speed * delta; + bullet.position.y += bullet.direction.y * speed * delta; + + if (bullet.position.x < -radius * 2 or + bullet.position.x > screen_size.x + radius * 2 or + bullet.position.y < -radius * 2 or + bullet.position.y > screen_size.y + radius * 2) + { + _ = self.bullets.orderedRemove(i); + } else { + raylib.DrawCircleV(bullet.position, radius, bullet.color); + i += 1; + } + } + } + + pub fn deinit(self: *Pool, allocator: std.mem.Allocator) void { + self.bullets.deinit(allocator); + } +}; diff --git a/src/main.zig b/src/main.zig @@ -1,14 +1,22 @@ const std = @import("std"); +const Bullet = @import("./bullet.zig"); const raylib = @import("raylib"); const raymath = @import("raymath"); pub fn main() !void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + const allocator = arena.allocator(); + const screen_width: f16 = 800.0; const screen_height: f16 = 1000.0; const fps: u8 = 60; - const player_movement_speed: f16 = 170.0; + const player_movement_speed: f16 = 140.0; const player_size: raylib.Vector2 = .{ .x = 50, .y = 50 }; + var bullet_pool: Bullet.Pool = .{}; + defer bullet_pool.deinit(allocator); + raylib.InitWindow(screen_width, screen_height, "1.44mb game jam"); defer raylib.CloseWindow(); @@ -21,22 +29,35 @@ pub fn main() !void { while (!raylib.WindowShouldClose()) { const delta: f32 = raylib.GetFrameTime(); - var direction: raylib.Vector2 = .{}; - if (raylib.IsKeyDown(raylib.KEY_RIGHT)) direction.x += 1; - if (raylib.IsKeyDown(raylib.KEY_LEFT)) direction.x -= 1; - if (raylib.IsKeyDown(raylib.KEY_UP)) direction.y -= 1; - if (raylib.IsKeyDown(raylib.KEY_DOWN)) direction.y += 1; + var player_direction: raylib.Vector2 = .{}; + if (raylib.IsKeyDown(raylib.KEY_RIGHT)) player_direction.x += 1; + if (raylib.IsKeyDown(raylib.KEY_LEFT)) player_direction.x -= 1; + if (raylib.IsKeyDown(raylib.KEY_UP)) player_direction.y -= 1; + if (raylib.IsKeyDown(raylib.KEY_DOWN)) player_direction.y += 1; - direction = @bitCast(raymath.Vector2Normalize(@bitCast(direction))); - player_position.x += direction.x * player_movement_speed * delta; - player_position.y += direction.y * player_movement_speed * delta; + player_direction = @bitCast(raymath.Vector2Normalize(@bitCast(player_direction))); + player_position.x += player_direction.x * player_movement_speed * delta; + player_position.y += player_direction.y * player_movement_speed * delta; const max_x: f32 = screen_width - player_size.x; const max_y: f32 = screen_height - player_size.y; player_position.x = @max(0, @min(max_x, player_position.x)); player_position.y = @max(0, @min(max_y, player_position.y)); + if (player_direction.x != 0 or player_direction.y != 0) { + if (bullet_pool.tick()) { + try bullet_pool.spawn( + allocator, + .{ + .x = player_position.x + (player_size.x / 2), + .y = player_position.y + (player_size.y / 2), + }, + player_direction, + ); + } + } + raylib.BeginDrawing(); defer raylib.EndDrawing(); @@ -47,5 +68,10 @@ pub fn main() !void { player_size, raylib.MAROON, ); + + bullet_pool.render(.{ + .x = screen_width, + .y = screen_height, + }); } } diff --git a/src/timer.zig b/src/timer.zig @@ -0,0 +1,15 @@ +const std = @import("std"); + +pub const Timer = struct { + duration: f32, + elapsed: f32 = 0, + + pub fn tick(self: *Timer, delta: f32) bool { + self.elapsed += delta; + if (self.elapsed >= self.duration) { + self.elapsed -= self.duration; + return true; + } + return false; + } +};