2024-07-25 02:11:58 +02:00
|
|
|
const gfx = @import("gfx");
|
|
|
|
|
|
|
|
const hid = @import("hid");
|
|
|
|
|
|
|
|
const ona = @import("ona");
|
|
|
|
|
|
|
|
const std = @import("std");
|
|
|
|
|
|
|
|
const Spawned = struct {
|
2024-07-27 02:44:06 +02:00
|
|
|
visual: struct {
|
|
|
|
color: gfx.Color,
|
2024-07-30 00:50:40 +02:00
|
|
|
position: gfx.Vector2,
|
|
|
|
rotation: f32,
|
2024-07-27 02:44:06 +02:00
|
|
|
},
|
|
|
|
|
2024-07-25 02:11:58 +02:00
|
|
|
lifetime_seconds: f32,
|
|
|
|
};
|
|
|
|
|
|
|
|
const Visuals = struct {
|
2024-07-27 02:44:06 +02:00
|
|
|
spawned: ona.stack.Parallel(Spawned) = .{},
|
2024-07-25 02:11:58 +02:00
|
|
|
random: std.Random.Xoroshiro128,
|
|
|
|
mouse_position: @Vector(2, f32) = @splat(0),
|
|
|
|
};
|
|
|
|
|
|
|
|
fn cleanup(visuals: ona.Write(Visuals)) !void {
|
2024-07-27 02:44:06 +02:00
|
|
|
visuals.state.spawned.deinit();
|
2024-07-25 02:11:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn load(visuals: ona.Write(Visuals)) !void {
|
|
|
|
const initial_spawn_capacity = 1024;
|
|
|
|
|
2024-07-27 02:44:06 +02:00
|
|
|
try visuals.state.spawned.grow(initial_spawn_capacity);
|
2024-07-25 02:11:58 +02:00
|
|
|
}
|
|
|
|
|
2024-07-30 00:50:40 +02:00
|
|
|
pub const main = ona.App.game
|
|
|
|
.with_module(gfx)
|
|
|
|
.with_module(hid)
|
|
|
|
.with_state(Visuals{.random = std.Random.Xoroshiro128.init(47342563891212)})
|
|
|
|
.with_system(.load, ona.system_fn(load), .{.label = "load visuals"})
|
|
|
|
.with_system(.update, ona.system_fn(update), .{.label = "spawn visuals"})
|
|
|
|
.with_system(.render, ona.system_fn(render), .{.label = "render visuals"})
|
|
|
|
.with_system(.exit, ona.system_fn(cleanup), .{.label = "clean up visuals"}).build();
|
2024-07-25 02:11:58 +02:00
|
|
|
|
2024-07-25 15:25:55 +02:00
|
|
|
fn update(visuals: ona.Write(Visuals), events: ona.Receive(hid.Event), display: ona.Read(gfx.Display)) !void {
|
2024-07-27 02:44:06 +02:00
|
|
|
update_spawned(&visuals.state.spawned);
|
2024-07-25 02:11:58 +02:00
|
|
|
|
|
|
|
const random = visuals.state.random.random();
|
|
|
|
const width: f32 = @floatFromInt(display.state.width);
|
|
|
|
const height: f32 = @floatFromInt(display.state.height);
|
|
|
|
|
|
|
|
for (events.messages()) |event| {
|
|
|
|
switch (event) {
|
|
|
|
.key_down => {
|
2024-07-27 02:44:06 +02:00
|
|
|
try visuals.state.spawned.push_grow(.{
|
2024-07-25 02:11:58 +02:00
|
|
|
.lifetime_seconds = 2.5 + (5 * random.float(f32)),
|
|
|
|
|
2024-07-27 02:44:06 +02:00
|
|
|
.visual = .{
|
|
|
|
.color = .{random.float(f32), random.float(f32), random.float(f32), random.float(f32)},
|
2024-07-30 00:50:40 +02:00
|
|
|
.position = .{width * random.float(f32), height},
|
|
|
|
.rotation = std.math.pi * random.float(f32),
|
2024-07-27 02:44:06 +02:00
|
|
|
},
|
2024-07-25 02:11:58 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
.mouse_down => {
|
2024-07-27 02:44:06 +02:00
|
|
|
try visuals.state.spawned.push_grow(.{
|
2024-07-25 02:11:58 +02:00
|
|
|
.lifetime_seconds = 2.5 + (5 * random.float(f32)),
|
|
|
|
|
2024-07-27 02:44:06 +02:00
|
|
|
.visual = .{
|
|
|
|
.color = .{random.float(f32), random.float(f32), random.float(f32), random.float(f32)},
|
2024-07-30 00:50:40 +02:00
|
|
|
.position = visuals.state.mouse_position,
|
|
|
|
.rotation = std.math.pi * random.float(f32),
|
2024-07-27 02:44:06 +02:00
|
|
|
},
|
2024-07-25 02:11:58 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
.mouse_motion => |motion| {
|
|
|
|
visuals.state.mouse_position = motion.absolute_position;
|
|
|
|
},
|
|
|
|
|
|
|
|
else => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-25 15:25:55 +02:00
|
|
|
fn update_spawned(spawned: *ona.stack.Parallel(Spawned)) void {
|
|
|
|
const float_speed = 6;
|
2024-07-25 02:11:58 +02:00
|
|
|
|
2024-07-27 02:44:06 +02:00
|
|
|
for (spawned.values.slice(.visual)) |*visual| {
|
2024-07-30 00:50:40 +02:00
|
|
|
visual.position -= .{0, float_speed};
|
2024-07-25 02:11:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
var range = spawned.len();
|
|
|
|
var index: usize = 0;
|
|
|
|
|
|
|
|
while (index < range) : (index += 1) {
|
|
|
|
const lifetime_seconds = spawned.values.get(.lifetime_seconds, index).?;
|
|
|
|
|
2024-07-25 15:25:55 +02:00
|
|
|
lifetime_seconds.* -= 1.0 / 60.0;
|
2024-07-25 02:11:58 +02:00
|
|
|
|
|
|
|
if (lifetime_seconds.* <= 0) {
|
|
|
|
range -= 1;
|
|
|
|
|
|
|
|
std.mem.swap(f32, lifetime_seconds, spawned.values.get(.lifetime_seconds, range).?);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.assert(spawned.pop_many(spawned.len() - range));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-30 00:50:40 +02:00
|
|
|
fn render(visuals: ona.Write(Visuals), commands: gfx.Commands(.foreground)) !void {
|
2024-07-27 02:44:06 +02:00
|
|
|
for (visuals.state.spawned.values.slice(.visual)) |visual| {
|
2024-07-30 00:50:40 +02:00
|
|
|
try commands.draw_texture(.{
|
|
|
|
.anchor = @splat(0.5),
|
|
|
|
.position = visual.position,
|
|
|
|
.tint = visual.color,
|
|
|
|
.size = @as(gfx.Vector2, @splat(64)),
|
2024-07-25 02:11:58 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|