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 d4a98d928be48c21ce048e7af94d33d7b6f126ec
parent 195ad8e997bf6ecf910a3ee185ecbbdb89f69cd4
Author: brookjeynes <me@brookjeynes.dev>
Date:   Thu, 13 Aug 2026 13:07:38 +1000

fix: don't despawn bullets after enemy dies

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

Diffstat:
Msrc/bullet.zig | 10++++++++++
Msrc/enemy_types/blorb.zig | 2+-
Msrc/enemy_types/grunt.zig | 1+
Msrc/main.zig | 2++
Msrc/player.zig | 2+-
Msrc/state.zig | 43+++++++++++++++++++++++++++++++++++++++----
6 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/src/bullet.zig b/src/bullet.zig @@ -11,6 +11,7 @@ pub const Bullet = struct { position: raylib.Vector2, velocity: raylib.Vector2, color: raylib.Color, + damage: f32, }; pub const Pool = struct { @@ -27,12 +28,14 @@ pub const Pool = struct { position: raylib.Vector2, velocity: raylib.Vector2, colour: raylib.Color, + damage: f32, ) void { if (self.count == self.bullets.len) return; self.bullets[self.count] = .{ .position = position, .velocity = velocity, .color = colour, + .damage = damage, }; self.count += 1; } @@ -68,4 +71,11 @@ pub const Pool = struct { i += 1; } } + + pub fn transferFrom(self: *Pool, src: *Pool) void { + const n = @min(src.count, self.bullets.len - self.count); + @memcpy(self.bullets[self.count .. self.count + n], src.bullets[0..n]); + self.count += n; + src.count = 0; + } }; diff --git a/src/enemy_types/blorb.zig b/src/enemy_types/blorb.zig @@ -41,7 +41,7 @@ pub fn shoot(self: *Blorb) void { 2 => .{ .x = 0, .y = self.bullet_speed }, else => .{ .x = -self.bullet_speed, .y = 0 }, }; - self.bullet_pool.spawn(spawn_position, bullet_velocity, raylib.PURPLE); + self.bullet_pool.spawn(spawn_position, bullet_velocity, raylib.PURPLE, bullet_damage); } self.shoot_offset +%= 1; diff --git a/src/enemy_types/grunt.zig b/src/enemy_types/grunt.zig @@ -30,6 +30,7 @@ pub fn shoot(self: *Grunt) void { .y = self.direction.y * self.bullet_speed, }, raylib.RED, + bullet_damage, ); } diff --git a/src/main.zig b/src/main.zig @@ -178,6 +178,8 @@ pub fn main() !void { game_state.enemies[idx].render(); } + game_state.orphaned_bullet_pool.render(.{ .x = constants.screen_width, .y = constants.screen_height }); + // Health overlay const health_percent: f32 = @max( 0, diff --git a/src/player.zig b/src/player.zig @@ -108,6 +108,6 @@ pub fn shoot(self: *Player) void { .x = dir.x * self.bullet_speed, .y = dir.y * self.bullet_speed, }; - self.bullet_pool.spawn(center, bullet_vel, raylib.BLUE); + self.bullet_pool.spawn(center, bullet_vel, raylib.BLUE, 1); } } diff --git a/src/state.zig b/src/state.zig @@ -3,8 +3,8 @@ const raymath = @import("raymath"); const Bullet = @import("./bullet.zig"); const constants = @import("./constants.zig"); -const Grunt = @import("./enemy_types/grunt.zig"); const Blorb = @import("./enemy_types/blorb.zig"); +const Grunt = @import("./enemy_types/grunt.zig"); const Entity = @import("./entity.zig").Entity; const EntityType = @import("./entity.zig").EntityType; const Player = @import("./player.zig"); @@ -31,11 +31,20 @@ pub const GameState = struct { grunt_spawn_time: Timer = .{ .duration = constants.grunt_spawn_time }, blorb_spawn_time: Timer = .{ .duration = constants.blorb_spawn_time }, + orphaned_bullet_pool: Bullet.Pool, + pub fn init() GameState { return .{ .screen = .title, .time = 0, + .orphaned_bullet_pool = .{ + .bullets = undefined, + .fire_timer = .{ + .duration = 0, + }, + }, + .player = .{ .bullet_pool = .{ .bullets = undefined, @@ -78,6 +87,8 @@ pub const GameState = struct { self.enemy_count = 0; self.enemies_killed = 0; + self.orphaned_bullet_pool.count = 0; + self.grunt_spawn_time = .{ .duration = constants.grunt_spawn_time }; self.blorb_spawn_time = .{ .duration = constants.blorb_spawn_time }; @@ -160,7 +171,7 @@ pub const GameState = struct { if (is_collision) { grunt.bullet_pool.despawn(enemy_bullet_idx); - self.player.handleDamage(Grunt.bullet_damage); + self.player.handleDamage(bullet.damage); } } @@ -185,6 +196,7 @@ pub const GameState = struct { if (is_collision) { self.player.bullet_pool.despawn(player_bullet_idx); + self.orphaned_bullet_pool.transferFrom(&grunt.bullet_pool); self.despawn_enemy(enemy_idx); self.enemies_killed += 1; continue :lbl; @@ -210,7 +222,7 @@ pub const GameState = struct { if (is_collision) { blorb.bullet_pool.despawn(enemy_bullet_idx); - self.player.handleDamage(Blorb.bullet_damage); + self.player.handleDamage(bullet.damage); } } @@ -234,6 +246,7 @@ pub const GameState = struct { ); if (is_collision) { + self.orphaned_bullet_pool.transferFrom(&blorb.bullet_pool); self.player.bullet_pool.despawn(player_bullet_idx); self.despawn_enemy(enemy_idx); self.enemies_killed += 1; @@ -245,6 +258,28 @@ pub const GameState = struct { enemy_idx += 1; } + + var enemy_bullet_idx = self.orphaned_bullet_pool.count; + while (enemy_bullet_idx > 0) { + enemy_bullet_idx -= 1; + + const bullet = self.orphaned_bullet_pool.bullets[enemy_bullet_idx]; + const is_collision = raylib.CheckCollisionCircleRec( + .{ .x = bullet.position.x, .y = bullet.position.y }, + Bullet.radius, + .{ + .x = self.player.position.x, + .y = self.player.position.y, + .width = self.player.size.x, + .height = self.player.size.y, + }, + ); + + if (is_collision) { + self.orphaned_bullet_pool.despawn(enemy_bullet_idx); + self.player.handleDamage(bullet.damage); + } + } } }; @@ -311,7 +346,7 @@ fn createEnemy( blorb.movement_speed = @min(160.0, 40.0 * difficulty); blorb.bullet_speed = @min(300.0, 100.0 * difficulty); - blorb.bullet_pool.fire_timer.duration = @max(0.3, 2.0 / difficulty); + blorb.bullet_pool.fire_timer.duration = @max(0.3, 4.0 / difficulty); blorb.setRandomDirection(); break :lbl .{ .blorb = blorb };