diff --git a/src/game_state.zig b/src/game_state.zig index dd5e42a..7899909 100644 --- a/src/game_state.zig +++ b/src/game_state.zig @@ -18,7 +18,7 @@ pub const GameStateController = struct { SCREEN_HEIGHT: u32 = 480, slime_factory_controller: sf.SlimeFactoryController = undefined, game_text_factory_controller: text.GameTextFactoryController = undefined, - prev_game_state: *GameState = undefined, + prev_game_state: ?*GameState = null, current_game_state: *GameState = undefined, renderer: *sdl.struct_SDL_Renderer = undefined, rng: std.Random = undefined, @@ -51,6 +51,11 @@ pub const GameStateController = struct { pub fn deinit(self: *GameStateController) void { self.slime_factory_controller.deinit(); + + self.allocator.destroy(self.current_game_state); + if (self.prev_game_state) |gs| { + self.allocator.destroy(gs); + } } // Physics main loop that processes variable time steps @@ -114,10 +119,12 @@ pub const GameStateController = struct { // sdl.SDL_Delay(100); var game_state = try self.allocator.create(GameState); - game_state.allocator = self.allocator; + if (self.prev_game_state) |prev_gs| { + self.allocator.destroy(prev_gs); + } game_state.slime_factory = try self.slime_factory_controller.spawnFactory(self.allocator); game_state.fps_timer = &self.fps_timer; - game_state.phys_ticks = @floatFromInt(self.phys_timer.getTicks()); + game_state.phys_ticks = self.phys_timer.getTicks(); game_state.phys_updates_since_render = self.phys_updates_since_last_render; // self.allocator.destroy(self.prev_game_state); @@ -145,7 +152,7 @@ pub const GameStateController = struct { } fn getFpsText(self: *GameStateController, buf: []u8) ![:0]const u8 { - const ticks_f: f64 = @floatFromInt(self.fps_timer.getTicks()); + const ticks_f: f64 = self.fps_timer.getTicks(); const frames_f: f64 = @floatFromInt(self.frames); const avg_fps: f64 = @round(frames_f / (ticks_f / 1000.0)); return try std.fmt.bufPrintZ(buf, "{d} fps", .{avg_fps}); @@ -153,38 +160,37 @@ pub const GameStateController = struct { }; pub const GameState = struct { - allocator: std.mem.Allocator, slime_factory: sf.SlimeFactory = undefined, fps_timer: *Timer, phys_ticks: f64, phys_updates_since_render: u32, // Checks all struct fields in GameState and calls deinit - pub fn deinit(self: *const GameState) void { - const game_state_info = @typeInfo(GameState); - switch (game_state_info) { - .Struct => { - inline for (game_state_info.Struct.fields) |field| { - switch (@typeInfo(field.type)) { - .Struct => { - // const inner_struct_info = @typeInfo(field.type); + // pub fn deinit(self: *const GameState) void { + // const game_state_info = @typeInfo(GameState); + // switch (game_state_info) { + // .Struct => { + // inline for (game_state_info.Struct.fields) |field| { + // switch (@typeInfo(field.type)) { + // .Struct => { + // // const inner_struct_info = @typeInfo(field.type); - // Check if struct has `deinit` method - if (@hasDecl(field.type, "deinit")) { - const field_ptr = @field(self, field.name); - field_ptr.deinit(); - std.debug.print("Deinit called on {s}\n", .{field.name}); - } - }, - else => {}, - } - } - }, + // // Check if struct has `deinit` method + // if (@hasDecl(field.type, "deinit")) { + // const field_ptr = @field(self, field.name); + // field_ptr.deinit(); + // std.debug.print("Deinit called on {s}\n", .{field.name}); + // } + // }, + // else => {}, + // } + // } + // }, - else => {}, - } + // else => {}, + // } - // Loop over fields of `GameState` + // Loop over fields of `GameState` - self.allocator.destroy(self); - } + // self.allocator.destroy(self); + // } }; diff --git a/src/main.zig b/src/main.zig index 37ed154..bd47543 100644 --- a/src/main.zig +++ b/src/main.zig @@ -38,6 +38,9 @@ pub fn main() !void { var quit = false; + var game_timer = Timer{}; + game_timer.start(); + var frame_time = Timer{}; frame_time.start(); @@ -72,9 +75,10 @@ pub fn main() !void { // Wait for time to render screen, keep running physics accumulator = accumulator + SCREEN_TICKS_PER_FRAME; const total_phys_ticks: u32 = @intFromFloat(PHYS_TICKS_PER_UPDATE * PHYS_UPDATES_PER_RENDER); - const phys_done_at_ticks: u32 = sdl.SDL_GetTicks() + total_phys_ticks; + const game_time_ms: u32 = @intFromFloat(game_timer.getTicks()); + const phys_done_at_ticks: u32 = game_time_ms + total_phys_ticks; var phys_ticks_used: f64 = 0; - std.debug.print("phys ticks/upd: {d}, Acc: {d}\nTotal phys ticks {d}ms\nPhys done at {d}ms\n", .{ PHYS_TICKS_PER_UPDATE, accumulator, total_phys_ticks, phys_done_at_ticks }); + std.debug.print("Phys ticks/upd: {d}\nAcc: {d}\nTotal phys ticks {d}ms\nPhys done at {d}ms\n", .{ PHYS_TICKS_PER_UPDATE, accumulator, total_phys_ticks, phys_done_at_ticks }); // Run a physics update while (accumulator >= PHYS_TICKS_PER_UPDATE) { // Control loop here @@ -86,6 +90,7 @@ pub fn main() !void { }, sdl.SDL_KEYDOWN => { switch (event.key.keysym.sym) { + sdl.SDLK_RETURN => {}, else => {}, } log("Got key event: %i\n", event.key.keysym.sym); @@ -96,23 +101,24 @@ pub fn main() !void { prev_game_state = current_game_state; current_game_state = try game_state_controller.update_tick(); const phys_ticks_this_update: f64 = current_game_state.?.phys_ticks - phys_ticks_used; + accumulator -= phys_ticks_this_update; - std.debug.print(" PU in {d}ms ", .{phys_ticks_this_update}); - std.debug.print(" Acc:{d} - ", .{accumulator}); + // std.debug.print(" PU in {d}ms ", .{phys_ticks_this_update}); + // std.debug.print(" Acc:{d} - ", .{accumulator}); // TODO dont turn it into an int, take the extra phys_frames and do a partial render - if (phys_ticks_this_update < PHYS_TICKS_PER_UPDATE) { - const ticks: u32 = @intFromFloat(PHYS_TICKS_PER_UPDATE - phys_ticks_this_update); - sdl.SDL_Delay(ticks); - accumulator -= PHYS_TICKS_PER_UPDATE; - } else { - std.debug.print("\nPHYSICS JANK\nPhysics Update took {d}ms, target: {d}ms\n", .{ phys_ticks_this_update, PHYS_TICKS_PER_UPDATE }); - accumulator -= phys_ticks_this_update; - } + // if (phys_ticks_this_update < PHYS_TICKS_PER_UPDATE) { + // const ticks: u32 = @intFromFloat(PHYS_TICKS_PER_UPDATE - phys_ticks_this_update); + // sdl.SDL_Delay(ticks); + // const ticksf: f64 = @floatFromInt(ticks); + // accumulator -= (phys_ticks_this_update + ticksf); + // } else { + // // std.debug.print("PHYSICS JANK: Physics Update took {d}ms, target: {d}ms\n", .{ phys_ticks_this_update, PHYS_TICKS_PER_UPDATE }); + // accumulator -= phys_ticks_this_update; + // } phys_ticks_used = current_game_state.?.phys_ticks; - std.debug.print(" PhyTicks this render: {d} ", .{current_game_state.?.phys_ticks}); + // std.debug.print(" PhyTicks this render: {d} ", .{current_game_state.?.phys_ticks}); } - // TODO lerp together prev and current states // Otherwise will have physics jank @@ -120,7 +126,7 @@ pub fn main() !void { std.debug.print("Took {d} phys frames\n", .{current_game_state.?.phys_updates_since_render}); try game_state_controller.render(current_game_state.?); - prev_frame_ms = @floatFromInt(frame_time.getTicks()); + prev_frame_ms = frame_time.getTicks(); std.debug.print("Rendered to screen in {d}ms\n***\n***\n", .{prev_frame_ms}); frame_time.reset(); // const frame_time_ticks = frame_time.getTicks(); diff --git a/src/utils/timer.zig b/src/utils/timer.zig index f1a2be6..1d1a081 100644 --- a/src/utils/timer.zig +++ b/src/utils/timer.zig @@ -1,57 +1,62 @@ const sdl = @import("./../sdl.zig").c; +const std = @import("std"); pub const TimerStatus = enum { started, stopped, paused }; pub const Timer = struct { - start_ticks_ms: u32 = 0, - pause_ticks_ms: u32 = 0, + start_ticks_ns: f64 = 0.0, + pause_ticks_ns: f64 = 0.0, status: TimerStatus = TimerStatus.stopped, pub fn start(self: *Timer) void { if (self.status == .started) return; self.status = .started; - self.start_ticks_ms = sdl.SDL_GetTicks(); - self.pause_ticks_ms = 0; + self.start_ticks_ns = @floatFromInt(std.time.nanoTimestamp()); + self.pause_ticks_ns = 0; } pub fn stop(self: *Timer) void { if (self.status == .stopped) return; self.status = .stopped; - self.start_ticks_ms = 0; - self.pause_ticks_ms = 0; + self.start_ticks_ns = 0; + self.pause_ticks_ns = 0; } // Resets the timer to 0 and starts it pub fn reset(self: *Timer) void { self.status = .started; - self.start_ticks_ms = sdl.SDL_GetTicks(); - self.pause_ticks_ms = 0; + self.start_ticks_ns = @floatFromInt(std.time.nanoTimestamp()); + self.pause_ticks_ns = 0; } pub fn pause(self: *Timer) void { if (self.status == .paused or self.status == .stopped) return; self.status = .paused; - self.pause_ticks_ms = sdl.SDL_GetTicks(); + const ns_stampf: f64 = @floatFromInt(std.time.nanoTimestamp()); + self.pause_ticks_ns = (ns_stampf - self.start_ticks_ns) / 1_000_000; } pub fn unpause(self: *Timer) void { if (self.status == .started or self.status == .stopped) return; self.status = .started; - self.start_ticks_ms = sdl.SDL_GetTicks() - self.pause_ticks_ms; - self.pause_ticks_ms = 0; + const ns_stampf: f64 = @floatFromInt(std.time.nanoTimestamp()); + const diff_ns: f64 = ns_stampf - self.pause_ticks_ns; + self.start_ticks_ns = self.start_ticks_ns + diff_ns; + self.pause_ticks_ns = 0; } // Gets the current tick/ms of the timer - pub fn getTicks(self: *Timer) u32 { + pub fn getTicks(self: *Timer) f64 { switch (self.status) { .stopped => { return 0; }, .paused => { - return self.pause_ticks_ms; + return self.pause_ticks_ns / 1_000_000; }, .started => { - return sdl.SDL_GetTicks() - self.start_ticks_ms; + const ns_stampf: f64 = @floatFromInt(std.time.nanoTimestamp()); + return (ns_stampf - self.start_ticks_ns) / 1_000_000; }, } }