Интерполяция¶
Интерполяция — одна из самых базовых операций в программировании графики. Будет неплохо с ней ознакомиться, дабы расширить Ваши горизонты как разработчика графики.
The basic idea is that you want to transition from A to B. A value t
, represents the states in-between.
Например, если переменная t
равна 0, тогда состояние равняется A. Если же t
равна 1, тогда состояние равняется B. Всё, что между ними, зовётся интерполяцией.
Between two real (floating-point) numbers, a simple interpolation is usually described as:
interpolation = A * (1 - t) + B * t
И часто сокращается до:
interpolation = A + (B - A) * t
Такая интерполяция, изменяющая одно значение на другое с постоянной скоростью, называется линейной. Поэтому, всякий раз, когда Вы услышите Линейная интерполяция, то будете знать, что имеется в виду эта простая формула.
Существуют другие типы интерполяций, о которых мы не будем здесь говорить. Чтобы прочесть о них, Вам рекомендуется проследовать на страницу Bezier.
Векторная интерполяция¶
Векторные типы (Vector2 и Vector3) тоже могут быть интерполированы, так как реализуют подходящие для этого функции Vector2.linear_interpolate() и Vector3.linear_interpolate().
For cubic interpolation, there are also Vector2.cubic_interpolate() and Vector3.cubic_interpolate(), which do a Bezier style interpolation.
Ниже приведён простой псевдокод, осуществляющий переход из точки A в точку B с использованием интерполяции:
var t = 0.0
func _physics_process(delta):
t += delta * 0.4
$Sprite.position = $A.position.linear_interpolate($B.position, t)
private float _t = 0.0f;
public override void _PhysicsProcess(float delta)
{
_t += delta * 0.4f;
Position2D a = GetNode<Position2D>("A");
Position2D b = GetNode<Position2D>("B");
Sprite sprite = GetNode<Sprite>("Sprite");
sprite.Position = a.Position.LinearInterpolate(b.Position, _t);
}
It will produce the following motion:

Интерполяция трансформаций¶
It is also possible to interpolate whole transforms (make sure they have either uniform scale or, at least, the same non-uniform scale). For this, the function Transform.interpolate_with() can be used.
Вот пример трансформирования обезьяны с первой позиции (Position1) на вторую (Position2):

Using the following pseudocode:
var t = 0.0
func _physics_process(delta):
t += delta
$Monkey.transform = $Position1.transform.interpolate_with($Position2.transform, t)
private float _t = 0.0f;
public override void _PhysicsProcess(float delta)
{
_t += delta;
Position3D p1 = GetNode<Position3D>("Position1");
Position3D p2 = GetNode<Position3D>("Position2");
CSGMesh monkey = GetNode<CSGMesh>("Monkey");
monkey.Transform = p1.Transform.InterpolateWith(p2.Transform, _t);
}
And again, it will produce the following motion:

Smoothing motion¶
Интерполяция может быть использована для сглаживания движений, поворотов, и т. п. Вот пример круга, следующего за мышкой с использованием плавного движения:
const FOLLOW_SPEED = 4.0
func _physics_process(delta):
var mouse_pos = get_local_mouse_position()
$Sprite.position = $Sprite.position.linear_interpolate(mouse_pos, delta * FOLLOW_SPEED)
private const float FollowSpeed = 4.0f;
public override void _PhysicsProcess(float delta)
{
Vector2 mousePos = GetLocalMousePosition();
Sprite sprite = GetNode<Sprite>("Sprite");
sprite.Position = sprite.Position.LinearInterpolate(mousePos, delta * FollowSpeed);
}
Here is how it looks:

Это полезно для плавного движения камеры, союзников, следующих за вами (гарантируя, что они находятся в определённом радиусе) и для многих других распространённых игровых паттернов.