Как исправить дрожание, вызванное интерполяцией положения - PullRequest
0 голосов
/ 08 февраля 2019

Я хочу интерполировать положение объекта по времени, я использую Pygame.

Когда игра хочет переместить объект в позицию, она вызывает interpolate_position с той позицией, которую она хочет, и сколько времени она хочет, чтобы интерполяция заняла.update вызывается в основном игровом цикле.Этот код является частью класса GameObject:

    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

Мой код иногда работает нормально, но в других случаях, когда объект должен оставаться неподвижным, он работаетвперед и назад в каком-то направлении на один пиксель.Моим главным предположением будет какая-то ошибка округления.Что я могу сделать, чтобы это исправить?Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Ошибка произошла потому, что пункт назначения и текущая позиция были одинаковыми .Я добавил проверку, чтобы предотвратить это, и теперь все работает.

0 голосов
/ 08 февраля 2019

Если вы хотите зафиксировать val в диапазоне [0, 1], то я бы предпочел использовать min() и max():

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

self.start_lerp непрерывно увеличивается до тех пор, пока не «достигнет» 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:
    # [...]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...