From 01c6d334f76dd8f0b325cbf28d852f900a89aec9 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Fri, 2 Oct 2026 01:41:58 +0300 Subject: [PATCH] add position interpolation --- src/app.zig | 40 +++++++++++++++++++++++++++++----------- src/platform/root.zig | 3 +-- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/app.zig b/src/app.zig index 513b6c9..885ef8e 100644 --- a/src/app.zig +++ b/src/app.zig @@ -450,6 +450,7 @@ fn loadLevel( .x = @intCast(ox), .y = @intCast(oy), }, + .visual_pos = .initFromInt(usize, ox, oy), .sprite = self.tilesheet.get(pos.x, pos.y) }); } @@ -506,6 +507,8 @@ pub fn frame(self: *App, plt: Platform.Frame) !void { canvas.push(); defer canvas.pop(clear_color); + const dt = plt.deltaTime(); + if (input.undo) { if (self.undo_stack.pop()) |undo_frame| { for (undo_frame.entities()) |e_state| { @@ -525,8 +528,12 @@ pub fn frame(self: *App, plt: Platform.Frame) !void { { var entity_iter = self.world.entities.iterator(); while (entity_iter.next()) |entity_id| { + var interpolate_pos = false; + const entity = self.world.entities.getAssumeExists(entity_id); if (entity.type == .player) { + interpolate_pos = true; + const prev_player_direction = entity.player_direction; if (tick_context.moveEntity(entity_id, input.move_dir)) { if (entity.player_direction != prev_player_direction) { @@ -536,9 +543,30 @@ pub fn frame(self: *App, plt: Platform.Frame) !void { self.footstep_sound = Audio.play(.{ .buffer = self.footstep_buffer, .bus = self.sfx_bus }); } + } else if (entity.type == .box_goal) { + goal_count += 1; + + if (self.world.entities.get(self.world.findEntity(entity.pos, .surface))) |above_entity| { + if (above_entity.type == .box) { + box_at_goal_count += 1; + } + } + } else if (entity.type == .box) { + interpolate_pos = true; + } + + const target_visual_pos = Vec2.initFromInt(i32, entity.pos.x, entity.pos.y); + var visual_step = target_visual_pos.sub(entity.visual_pos); + if (interpolate_pos) { + const speed = 10; + visual_step = visual_step.multiplyScalar(dt * speed); + } + entity.visual_pos = entity.visual_pos.add(visual_step); + + if (entity.type == .player) { const frames = self.player_sprites.getDirection(entity.player_direction); - if (input.move_dir.x != 0 or input.move_dir.y != 0) { + if (target_visual_pos.sub(entity.visual_pos).length() > 0.1) { self.animation_timer += plt.input.delta_time; const animatin_time = std.time.ns_per_s / 5; while (self.animation_timer >= animatin_time) { @@ -551,17 +579,7 @@ pub fn frame(self: *App, plt: Platform.Frame) !void { } entity.sprite = frames[entity.player_frame_index]; - } else if (entity.type == .box_goal) { - goal_count += 1; - - if (self.world.entities.get(self.world.findEntity(entity.pos, .surface))) |above_entity| { - if (above_entity.type == .box) { - box_at_goal_count += 1; - } - } } - - entity.visual_pos = .initFromInt(i32, entity.pos.x, entity.pos.y); } } diff --git a/src/platform/root.zig b/src/platform/root.zig index ee6d4d4..f26eb7c 100644 --- a/src/platform/root.zig +++ b/src/platform/root.zig @@ -106,10 +106,9 @@ fn PlatformType(App: type) type { _ = self.frame_arena.reset(.free_all); // TODO: make arena reset mode configurable const now = Io.Timestamp.now(self.io, .awake); - self.last_frame_at = now; - self.input.now = @intCast(self.started_at.durationTo(now).nanoseconds); self.input.delta_time = @intCast(self.last_frame_at.durationTo(now).nanoseconds); + self.last_frame_at = now; if (self.input.keyboard.pressed.contains(.F4)) { self.show_imgui = !self.show_imgui;