Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Інтерполяція

Інтерполяція — це поширена операція в графічному програмуванні, яка використовується для змішування або переходу між двома значеннями. Інтерполяція також може бути використана для плавного руху, обертання тощо. Добре ознайомитися з нею, щоб розширити свій кругозір як розробника ігор.

Основна ідея полягає в тому, що ви хочете перейти від А до В. Значення t, представляє стани між ними.

Наприклад, якщо t дорівнює 0, тоді стан дорівнює A. Якщо t дорівнює 1, то стан дорівнює B. Все, що знаходиться між ними, є інтерполяцією.

Між двома дійсними числами (з плаваючою комою) інтерполяцію можна описати так:

interpolation = A * (1 - t) + B * t

І часто спрощується до:

interpolation = A + (B - A) * t

Назва цього типу інтерполяції, яка перетворює одне значення на інше з постійною швидкістю, — «лінійна». Тож, коли ви чуєте про лінійну інтерполяцію, ви знаєте, що вони мають на увазі цю формулу.

Є й інші види інтерполяції, які тут не будуть розглядатися. Тому, після цієї статті, рекомендується прочитати сторінку Bezier.

Векторна інтерполяція

Типи векторів (Vector2 і Vector3) також можна інтерполювати, вони мають зручні функції для цього Vector2.lerp() і Vector3.lerp().

Для кубічної інтерполяції існують також Vector2.cubic_interpolate() та Vector3.cubic_interpolate(), які виконують інтерполяцію в стилі Bezier.

Ось приклад псевдокоду для переходу від точки А до точки Б за допомогою інтерполяції:

var t = 0.0

func _physics_process(delta):
    t += delta * 0.4

    $Sprite2D.position = $A.position.lerp($B.position, t)

Він буде виробляти наступний рух:

../../_images/interpolation_vector.gif

Інтерполяція перетворень

Також можна інтерполювати цілі перетворення (переконайтеся, що вони мають або єдиний масштаб, або, принаймні, однаковий нерівномірний масштаб). Для цього можна використовувати функцію Transform3D.interpolate_with().

Ось приклад перетворення мавпочки з Позиції1 в Позицію2:

../../_images/interpolation_positions.png

За допомогою наступного псевдокоду:

var t = 0.0

func _physics_process(delta):
    t += delta

    $Monkey.transform = $Position1.transform.interpolate_with($Position2.transform, t)

Він буде виробляти наступний рух:

../../_images/interpolation_monkey.gif

Плавний рух

Інтерполяцію можна використовувати для плавного відстеження цільового значення, яке рухається, наприклад позиції або повороту. Кожен кадр lerp() переміщує поточне значення до цільового значення на фіксований відсоток різниці між значеннями, що залишилася. Поточне значення буде плавно рухатися до цілі, сповільнюючи швидкість у міру наближення. Ось приклад кола, яке слідує за мишею з використанням інтерполяційного згладжування:

const FOLLOW_SPEED = 4.0

func _physics_process(delta):
    var mouse_pos = get_local_mouse_position()

    $Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, delta * FOLLOW_SPEED)

Ось як це виглядає:

../../_images/interpolation_follow.gif

Це корисно для згладжування руху камери, для союзників, які стежать за гравцем (переконавшись, що вони залишаються в межах певного діапазону), і для багатьох інших типових ігрових шаблонів.

Примітка

Незважаючи на використання delta, використана вище формула залежить від частоти кадрів, оскільки параметр weight lerp() представляє відсоток різниці значень, що залишилася, а не абсолютну суму, яку потрібно змінити. У _physics_process() це зазвичай добре, оскільки очікується, що фізика підтримуватиме постійну частоту кадрів, і тому дельта має залишатися постійною.

Для незалежної від частоти кадрів версії інтерполяційного згладжування, яку також можна використовувати в process(), використовуйте натомість таку формулу:

const FOLLOW_SPEED = 4.0

func _process(delta):
    var mouse_pos = get_local_mouse_position()
    var weight = 1 - exp(-FOLLOW_SPEED * delta)
    $Sprite2D.position = $Sprite2D.position.lerp(mouse_pos, weight)

Отримання цієї формули виходить за рамки цієї сторінки. Щоб отримати пояснення, перегляньте Покращене згладжування Lerp або подивіться Згладжування Lerp порушено.