add money

This commit is contained in:
Rokas Puzonas 2026-01-31 13:29:40 +02:00
parent 8645f732c5
commit dc8d8e881a
2 changed files with 85 additions and 7 deletions

View File

@ -380,6 +380,10 @@ pub const Rect = struct {
}; };
} }
pub fn initCentered(x: f32, y: f32, width: f32, height: f32) Rect {
return init(x - width/2, y - height/2, width, height);
}
pub fn clip(self: Rect, other: Rect) Rect { pub fn clip(self: Rect, other: Rect) Rect {
const left_edge = @max(self.left(), other.left()); const left_edge = @max(self.left(), other.left());
const right_edge = @min(self.right(), other.right()); const right_edge = @min(self.right(), other.right());
@ -453,7 +457,7 @@ pub const Rect = struct {
} }
pub fn grow(self: Rect, amount: f32) Rect { pub fn grow(self: Rect, amount: f32) Rect {
return self.growX(self.growY(amount), amount); return self.growX(amount).growY(amount);
} }
}; };

View File

@ -55,7 +55,12 @@ const Kinetic = struct {
const Player = struct { const Player = struct {
kinetic: Kinetic = .{}, kinetic: Kinetic = .{},
last_shot_at: ?Nanoseconds = null money: u32 = 0,
last_shot_at: ?Nanoseconds = null,
pub fn getRect(self: Player) Rect {
return getCenteredRect(self.kinetic.pos, 16);
}
}; };
const Bullet = struct { const Bullet = struct {
@ -88,10 +93,20 @@ const Wave = struct {
}; };
}; };
const Pickup = struct {
const Kind = enum {
money
};
pos: Vec2,
kind: Kind,
};
const pickup_spawn_duration_s = Range.init(1, 5);
const wave_infos = [_]Wave.Info{ const wave_infos = [_]Wave.Info{
.{ .{
.enemies = 10, .enemies = 10,
.duration_s = 1, .duration_s = 10,
.starts_at_s = 0 .starts_at_s = 0
} }
}; };
@ -105,6 +120,9 @@ player: Player = .{},
bullets: std.ArrayList(Bullet) = .empty, bullets: std.ArrayList(Bullet) = .empty,
enemies: std.ArrayList(Enemy) = .empty, enemies: std.ArrayList(Enemy) = .empty,
pickups: std.ArrayList(Pickup) = .empty,
next_pickup_spawn_at: Nanoseconds,
wave_timer: Nanoseconds = 0, wave_timer: Nanoseconds = 0,
waves: std.ArrayList(Wave) = .empty, waves: std.ArrayList(Wave) = .empty,
@ -114,16 +132,22 @@ pub fn init(gpa: Allocator, seed: u64, assets: *Assets) !Game {
var arena = std.heap.ArenaAllocator.init(gpa); var arena = std.heap.ArenaAllocator.init(gpa);
errdefer arena.deinit(); errdefer arena.deinit();
var rng = RNGState.init(seed);
const next_pickup_spawn_at_s = pickup_spawn_duration_s.random(rng.random());
const next_pickup_spawn_at: Nanoseconds = @intFromFloat(next_pickup_spawn_at_s * std.time.ns_per_s);
return Game{ return Game{
.arena = arena, .arena = arena,
.gpa = gpa, .gpa = gpa,
.assets = assets, .assets = assets,
.next_pickup_spawn_at = next_pickup_spawn_at,
.player = .{ .player = .{
.kinetic = .{ .kinetic = .{
.pos = .init(50, 50), .pos = .init(50, 50),
} }
}, },
.rng = RNGState.init(seed), .rng = rng
}; };
} }
@ -132,6 +156,7 @@ pub fn deinit(self: *Game) void {
self.bullets.deinit(self.gpa); self.bullets.deinit(self.gpa);
self.enemies.deinit(self.gpa); self.enemies.deinit(self.gpa);
self.waves.deinit(self.gpa); self.waves.deinit(self.gpa);
self.pickups.deinit(self.gpa);
self.spawned_waves.deinit(self.gpa); self.spawned_waves.deinit(self.gpa);
} }
@ -184,6 +209,17 @@ fn spawnEnemy(self: *Game) !void {
}); });
} }
fn spawnPickup(self: *Game) !void {
const margin = 10;
const spawn_area = (Rect{ .pos = .zero, .size = world_size }).grow(-margin);
const pos = Vec2.initRandomRect(self.rng.random(), spawn_area);
try self.pickups.append(self.gpa, Pickup{
.pos = pos,
.kind = .money
});
}
pub fn tick(self: *Game, frame: *Engine.Frame) !void { pub fn tick(self: *Game, frame: *Engine.Frame) !void {
const dt = frame.deltaTime(); const dt = frame.deltaTime();
@ -202,7 +238,7 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
try self.spawned_waves.append(self.gpa, i); try self.spawned_waves.append(self.gpa, i);
try self.waves.append(self.gpa, .{ try self.waves.append(self.gpa, .{
.started_at = self.wave_timer, .started_at = self.wave_timer,
.duration = wave_info.duration_s * std.time.ns_per_s, .duration = @as(u64, wave_info.duration_s) * std.time.ns_per_s,
.enemies_spawned = 0, .enemies_spawned = 0,
.total_enemies = wave_info.enemies .total_enemies = wave_info.enemies
}); });
@ -237,6 +273,13 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
} }
} }
if (self.wave_timer >= self.next_pickup_spawn_at) {
const next_pickup_spawn_at_s = pickup_spawn_duration_s.random(self.rng.random());
const next_pickup_spawn_at: Nanoseconds = @intFromFloat(next_pickup_spawn_at_s * std.time.ns_per_s);
self.next_pickup_spawn_at = self.wave_timer + next_pickup_spawn_at;
try self.spawnPickup();
}
frame.graphics.canvas_size = world_size; frame.graphics.canvas_size = world_size;
if (frame.isKeyPressed(.F3)) { if (frame.isKeyPressed(.F3)) {
@ -306,7 +349,7 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
} }
frame.drawRectangle(.{ frame.drawRectangle(.{
.rect = getCenteredRect(self.player.kinetic.pos, 16), .rect = self.player.getRect(),
.color = rgb(255, 255, 255) .color = rgb(255, 255, 255)
}); });
@ -342,6 +385,32 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
}); });
} }
{
var index: usize = 0;
while (index < self.pickups.items.len) {
var destroy: bool = false;
const pickup = self.pickups.items[index];
const pickup_rect = Rect.initCentered(pickup.pos.x, pickup.pos.y, 10, 10);
if (pickup_rect.hasOverlap(self.player.getRect())) {
self.player.money += 1;
destroy = true;
}
frame.drawRectangle(.{
.rect = pickup_rect,
.color = rgb(20, 20, 200)
});
if (destroy) {
_ = self.pickups.swapRemove(index);
} else {
index += 1;
}
}
}
{ {
var i: usize = 0; var i: usize = 0;
while (i < self.bullets.items.len) { while (i < self.bullets.items.len) {
@ -371,6 +440,8 @@ pub fn tick(self: *Game, frame: *Engine.Frame) !void {
@divFloor(wave_timer_s, 60), @divFloor(wave_timer_s, 60),
@mod(wave_timer_s, 60) @mod(wave_timer_s, 60)
}); });
frame.drawTextFormat(.init(10, 30), text_opts, "{d}", .{ self.player.money });
} }
pub fn debug(self: *Game) !void { pub fn debug(self: *Game) !void {
@ -387,6 +458,9 @@ pub fn debug(self: *Game) !void {
try self.spawnEnemy(); try self.spawnEnemy();
} }
const time_left_til_pickup = self.next_pickup_spawn_at - self.wave_timer;
imgui.textFmt("Waves: {}\n", .{self.waves.items.len}); imgui.textFmt("Waves: {}\n", .{self.waves.items.len});
imgui.textFmt("Enemies: {}\n", .{self.enemies.items.len}); imgui.textFmt("Enemies: {}\n", .{self.enemies.items.len});
imgui.textFmt("Time until next pickup: {d:.2}s\n", .{@as(f32, @floatFromInt(time_left_til_pickup)) / std.time.ns_per_s});
} }