const gfx = @import("gfx"); const hid = @import("hid"); const ona = @import("ona"); const std = @import("std"); const Visuals = struct { spawned: SpawnMap = SpawnMap.init(ona.heap.allocator), random: std.Random.Xoroshiro128, mouse_position: @Vector(2, f32) = @splat(0), const SpawnMap = ona.SlotMap(struct { color: gfx.Color, position: gfx.Vector2, rotation: f32, lifetime_seconds: f32, }); }; fn cleanup(visuals: ona.Write(Visuals)) !void { visuals.state.spawned.deinit(); } pub const main = ona.App.game .with_module(gfx) .with_module(hid) .with_state(Visuals{.random = std.Random.Xoroshiro128.init(47342563891212)}) .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(); fn update(visuals: ona.Write(Visuals), events: ona.Receive(hid.Event), display: ona.Read(gfx.Display)) !void { const float_speed = 6; for (0 .. visuals.state.spawned.next) |i| { const spawned = visuals.state.spawned.get(i) orelse { continue; }; spawned.lifetime_seconds -= 1.0 / 60.0; spawned.position -= .{0, float_speed}; if (spawned.lifetime_seconds <= 0) { std.debug.assert(visuals.state.spawned.remove(i) != null); } } 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 => { _ = try visuals.state.spawned.insert(.{ .lifetime_seconds = 2.5 + (5 * random.float(f32)), .color = .{random.float(f32), random.float(f32), random.float(f32), random.float(f32)}, .position = .{width * random.float(f32), height}, .rotation = std.math.pi * random.float(f32), }); }, .mouse_down => { _ = try visuals.state.spawned.insert(.{ .lifetime_seconds = 2.5 + (5 * random.float(f32)), .color = .{random.float(f32), random.float(f32), random.float(f32), random.float(f32)}, .position = visuals.state.mouse_position, .rotation = std.math.pi * random.float(f32), }); }, .mouse_motion => |motion| { visuals.state.mouse_position = motion.absolute_position; }, else => {} } } } fn render(visuals: ona.Write(Visuals), commands: gfx.Commands) !void { for (visuals.state.spawned.values()) |visual| { try commands.draw_texture(.{ .anchor = @splat(0.5), .position = visual.position, .tint = visual.color, .size = @as(gfx.Vector2, @splat(64)), }); } }