Game now uses execution graph to schedule systems

This commit is contained in:
duck
2025-05-08 21:05:08 +05:00
parent d239e775f3
commit a87d86b335
6 changed files with 134 additions and 41 deletions

View File

@@ -1,48 +1,90 @@
const std = @import("std");
const builtin = @import("builtin");
const sdl = @import("sdl");
const Graph = @import("graph.zig");
const Graphics = @import("graphics.zig");
graphics: Graphics,
running: bool,
// TODO:
// - Do something about deallocating `Resource`s when `Graph` fails
const RunInfo = struct { running: bool };
alloc: std.mem.Allocator,
graph: Graph,
const Self = @This();
pub fn init() GameError!Self {
pub fn init(alloc: std.mem.Allocator) GameError!Self {
var graph = try Graph.init(alloc);
errdefer graph.deinit();
const graphics = try Graphics.create();
var controller = try graph.getController();
controller.addResource(graphics);
try graph.freeController(controller);
return Self{
.graphics = try Graphics.create(),
.running = false,
.alloc = alloc,
.graph = graph,
};
}
pub fn run(self: *Self) GameError!void {
self.running = true;
{
var controller = try self.graph.getController();
controller.addResource(RunInfo{ .running = true });
try self.graph.freeController(controller);
}
while (true) {
try self.processEvents();
if (!self.running) {
if (!self.graph.getResource(RunInfo).?.running) {
break;
}
try self.update();
try self.draw();
var controller = try self.graph.getController();
controller.queue(.{
.events = processEvents,
.draw = draw,
.ordered = true,
});
try self.graph.freeController(controller);
defer self.graph.reset();
try self.graph.runAllSystems();
}
}
fn update(self: *Self) GameError!void {
_ = self;
fn draw(graphics: *Graphics) GameError!void {
try graphics.beginDraw();
{
errdefer graphics.endDraw() catch {};
try graphics.drawDebug();
}
try graphics.endDraw();
}
fn draw(self: *Self) GameError!void {
try self.graphics.beginDraw();
try self.graphics.drawDebug();
try self.graphics.endDraw();
fn clean(graphics: *Graphics) !void {
graphics.destroy();
// TODO: Also remove the resource
}
fn processEvents(self: *Self) GameError!void {
fn processEvents(graphics: *Graphics, run_info: *RunInfo) GameError!void {
sdl.PumpEvents();
while (true) {
var buffer: [16]sdl.Event = undefined;
const count: usize = @intCast(sdl.PeepEvents(&buffer, buffer.len, sdl.GETEVENT, sdl.EVENT_FIRST, sdl.EVENT_LAST));
if (count == -1) return GameError.SdlError;
for (buffer[0..count]) |event| {
self.processEvent(event);
switch (event.type) {
sdl.EVENT_QUIT => {
run_info.running = false;
},
sdl.EVENT_WINDOW_RESIZED => {
if (event.window.windowID != sdl.GetWindowID(graphics.window)) return;
graphics.resize(@intCast(event.window.data1), @intCast(event.window.data2));
},
else => {},
}
}
if (count < buffer.len) {
break;
@@ -51,25 +93,21 @@ fn processEvents(self: *Self) GameError!void {
sdl.FlushEvents(sdl.EVENT_FIRST, sdl.EVENT_LAST);
}
fn processEvent(self: *Self, event: sdl.Event) void {
switch (event.type) {
sdl.EVENT_QUIT => {
self.running = false;
},
sdl.EVENT_WINDOW_RESIZED => {
if (event.window.windowID != sdl.GetWindowID(self.graphics.window)) return;
self.graphics.resize(@intCast(event.window.data1), @intCast(event.window.data2));
},
else => {},
}
}
pub fn deinit(self: *Self) void {
self.graphics.destroy();
var controller = self.graph.getController() catch unreachable;
controller.queue(clean);
self.graph.freeController(controller) catch unreachable;
self.graph.runAllSystems() catch unreachable;
self.graph.deinit();
sdl.Quit();
}
pub const GameError = error{
SdlError,
OSError,
OutOfMemory,
MissingResource,
SystemDeadlock,
};