diff --git a/source/ona/ona.zig b/source/ona/ona.zig index 12b7b73..46b4596 100755 --- a/source/ona/ona.zig +++ b/source/ona/ona.zig @@ -1,53 +1,66 @@ +pub const canvas = @import("./canvas.zig"); + const coral = @import("coral"); const ext = @import("./ext.zig"); pub const files = @import("./files.zig"); -pub const gfx = @import("./gfx.zig"); - pub const App = opaque { pub fn Starter(comptime errors: type) type { return fn (app_state: *App) errors!void; } const State = struct { - last_event: ext.SDL_Event, base_file_sandbox: files.FileSandbox, window: *ext.SDL_Window, renderer: *ext.SDL_Renderer, - canvas: gfx.Canvas, + last_tick: u64, + tick_rate: u64 = 16, + canvas_items: coral.slots.Dense(coral.slots.addressable_key, canvas.Item), fn cast(self: *App) *State { return @ptrCast(*State, @alignCast(@alignOf(State), self)); } }; - pub fn canvas(self: *App) *gfx.Canvas { - return &State.cast(self).canvas; - } - pub fn data_fs(self: *App) files.FileAccessor { return files.FileAccessor.bind(files.FileSandbox, &State.cast(self).base_file_sandbox); } - pub fn poll(self: *App) bool { + pub fn loop(self: *App) void { const state = State.cast(self); - while (ext.SDL_PollEvent(&state.last_event) != 0) switch (state.last_event.type) { - ext.SDL_QUIT => return false, - else => {}, - }; + while (true) { + const current_tick = ext.SDL_GetTicks64(); + var event = @as(ext.SDL_Event, undefined); - return true; - } + while (ext.SDL_PollEvent(&event) != 0) { + switch (event.type) { + ext.SDL_QUIT => return, + else => {}, + } + } - pub fn present(self: *App) void { - for (self.canvas().items.values) |item| { - switch (item) { - .sprite => { - // TODO: Implement. - }, + if ((current_tick - state.last_tick) >= state.tick_rate) { + // TODO: Perform game updates. + if (ext.SDL_SetRenderDrawColor(state.renderer, 255, 255, 255, 255) != 0) { + return log_error(&.{.{.string = coral.io.slice_sentineled(u8, 0, ext.SDL_GetError())}}); + } + + if (ext.SDL_RenderClear(state.renderer) != 0) { + return log_error(&.{.{.string = coral.io.slice_sentineled(u8, 0, ext.SDL_GetError())}}); + } + + for (state.canvas_items.values) |canvas_item| { + switch (canvas_item.options) { + .sprite => {}, + } + } + + ext.SDL_RenderPresent(state.renderer); + + state.last_tick = current_tick; } } } @@ -80,10 +93,10 @@ pub const App = opaque { defer ext.SDL_DestroyRenderer(renderer); return start(@ptrCast(*App, &App.State{ - .last_event = undefined, .window = window, .renderer = renderer, - .canvas = gfx.Canvas.init(allocator), + .last_tick = 0, + .canvas_items = .{}, .base_file_sandbox = .{ .prefix = coral.io.slice_sentineled(u8, 0, base_prefix), @@ -133,6 +146,24 @@ var heap = struct { } }{}; +pub const CanvasItem = struct { + app: *App, + id: coral.slots.Slot(coral.slots.addressable_key), + + pub fn deinit(self: *CanvasItem) void { + coral.debug.assert(App.State.cast(self.app).canvas_items.remove(self.id)); + } + + pub fn init(app: *App, canvas_item: canvas.Item) coral.io.AllocationError!CanvasItem { + const slot = try App.State.cast(app).canvas_items.insert(allocator, canvas_item); + + return CanvasItem{ + .app = app, + .id = slot, + }; + } +}; + pub fn log_debug(values: []const coral.format.Value) void { var message_memory = [_]u8{0} ** 4096; var message_buffer = coral.buffer.Fixed{.data = &message_memory};