如何修复位置插值引起的抖动

How to fix jitter caused by position interpolation

我想在一段时间内插入对象的位置,我正在使用 pygame。

当游戏想要将对象移动到一个位置时,它会调用 interpolate_position 以及它想要的位置和插值所需的时间。 update在基本游戏循环中调用。 此代码是 GameObject class:

的一部分
    def update(self, dt):
        if self.is_lerping:
            self.update_interpolate(dt)

    def update_interpolate(self, dt):
        if self.start_lerp - self.total_lerp_time <= 2 * dt:
            val = dt / (self.total_lerp_time - self.start_lerp)
            val = val if 0 < val < 1 else 1
            self.position = self.position.lerp(self.lerp_goal, val)
            self.start_lerp += dt
        else:
            self.position = self.lerp_goal
            self.is_lerping = False

    def interpolate_position(self, pos, lerp_time):
        self.is_lerping = True
        self.total_lerp_time = lerp_time
        self.start_lerp = 0
        self.lerp_goal = Vector2(pos)

更新是这样调用的:

AVERAGE_DELTA_MILLIS = round(float(1000) / 60, 4)
while True:
    before_update_and_render = self.clock.get_time()
    delta_millis = (update_duration_millis + sleep_duration_millis) / 1000            
    o.update(delta_millis)  #  Updates the object
    update_duration_millis = (self.clock.get_time() - before_update_and_render) * 1000
    sleep_duration_millis = max([2, AVERAGE_DELTA_MILLIS - update_duration_millis])
    time.sleep(sleep_duration_millis / 1000)  # Sleeps an amount of time so the game will be 60 fps

我的代码有时工作正常,但有时当对象应该静止时,它会在某个方向上来回移动一个像素。我的主要猜测是某种舍入误差。我该怎么做才能解决这个问题?提前致谢。

如果你想将 val 限制在 [0, 1] 范围内,那么我更愿意使用 min() and max():

val = max(0, min(val, 1))

self.start_lerp 不断递增,直到 "reaches" self.total_lerp_time.
所以条件 self.start_lerp - self.total_lerp_time <= 2 * dt 是错误的。

必须是:

if self.total_lerp_time - self.start_lerp > 2 * dt:
    # [...]

或者甚至更好地使用内置函数 abs(),它甚至可以用于负值:

if abs(self.total_lerp_time - self.start_lerp) > 2 * dt:
    # [...]

错误发生是因为目的地和当前位置相同。我添加了一项检查以防止出现这种情况,现在一切正常。