add position interpolation

This commit is contained in:
Rokas Puzonas 2026-10-02 01:41:58 +03:00
parent 66d0b32552
commit 01c6d334f7
2 changed files with 30 additions and 13 deletions

View File

@ -450,6 +450,7 @@ fn loadLevel(
.x = @intCast(ox), .x = @intCast(ox),
.y = @intCast(oy), .y = @intCast(oy),
}, },
.visual_pos = .initFromInt(usize, ox, oy),
.sprite = self.tilesheet.get(pos.x, pos.y) .sprite = self.tilesheet.get(pos.x, pos.y)
}); });
} }
@ -506,6 +507,8 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
canvas.push(); canvas.push();
defer canvas.pop(clear_color); defer canvas.pop(clear_color);
const dt = plt.deltaTime();
if (input.undo) { if (input.undo) {
if (self.undo_stack.pop()) |undo_frame| { if (self.undo_stack.pop()) |undo_frame| {
for (undo_frame.entities()) |e_state| { 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(); var entity_iter = self.world.entities.iterator();
while (entity_iter.next()) |entity_id| { while (entity_iter.next()) |entity_id| {
var interpolate_pos = false;
const entity = self.world.entities.getAssumeExists(entity_id); const entity = self.world.entities.getAssumeExists(entity_id);
if (entity.type == .player) { if (entity.type == .player) {
interpolate_pos = true;
const prev_player_direction = entity.player_direction; const prev_player_direction = entity.player_direction;
if (tick_context.moveEntity(entity_id, input.move_dir)) { if (tick_context.moveEntity(entity_id, input.move_dir)) {
if (entity.player_direction != prev_player_direction) { 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 }); 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); 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; self.animation_timer += plt.input.delta_time;
const animatin_time = std.time.ns_per_s / 5; const animatin_time = std.time.ns_per_s / 5;
while (self.animation_timer >= animatin_time) { 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]; 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);
} }
} }

View File

@ -106,10 +106,9 @@ fn PlatformType(App: type) type {
_ = self.frame_arena.reset(.free_all); // TODO: make arena reset mode configurable _ = self.frame_arena.reset(.free_all); // TODO: make arena reset mode configurable
const now = Io.Timestamp.now(self.io, .awake); 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.now = @intCast(self.started_at.durationTo(now).nanoseconds);
self.input.delta_time = @intCast(self.last_frame_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)) { if (self.input.keyboard.pressed.contains(.F4)) {
self.show_imgui = !self.show_imgui; self.show_imgui = !self.show_imgui;