О чем этот пример
Создание плавных анимаций и переходов — одна из ключевых задач в игровой разработке. Линейная интерполяция (lerp) — это математическая операция для нахождения промежуточной точки между двумя другими. В Phaser она доступна через метод `.lerp()` у объектов `Phaser.Math.Vector2`. Эта статья покажет, как использовать интерполяцию для создания динамической визуализации движения точки между двумя позициями, одна из которых управляется курсором. Этот приём полезен для следящих камер, плавного движения объектов к цели или создания траекторий.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
t = 0.5;
interpolatedPoint;
point2;
point1;
graphics;
create ()
{
this.graphics = this.add.graphics({ lineStyle: { width: 3, color: 0x2266aa }, fillStyle: { color: 0x2266aa } });
this.point1 = new Phaser.Math.Vector2(400, 300);
this.point2 = new Phaser.Math.Vector2(550, 300);
this.interpolatedPoint = this.point1.clone().lerp(this.point2, this.t);
this.input.on('pointermove', pointer =>
{
this.point2.copy(pointer);
});
}
update ()
{
this.graphics.clear();
this.t = (this.t + 0.01) % 1;
this.interpolatedPoint = this.point1.clone().lerp(this.point2, this.t);
this.graphics.fillPointShape(this.point1, 20);
this.graphics.fillPointShape(this.point2, 20);
this.graphics.fillStyle(0x00aa00);
this.graphics.fillPointShape(this.interpolatedPoint, 20);
this.graphics.lineBetween(this.point1.x, this.point1.y, this.point2.x, this.point2.y);
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Инициализация точек и графики
В начале кода в классе сцены объявляются свойства для хранения двух точек, интерполированной точки, графического объекта и коэффициента интерполяции `t`.
В методе create() создаётся графический контекст this.graphics для рисования. Инициализируются две точки: point1 — фиксированная точка в центре экрана, point2 — изначально расположена правее. Интерполированная точка вычисляется сразу при старте с помощью метода .lerp(). Также устанавливается обработчик события движения указателя, который обновляет позицию point2.
this.graphics = this.add.graphics({ lineStyle: { width: 3, color: 0x2266aa }, fillStyle: { color: 0x2266aa } });
this.point1 = new Phaser.Math.Vector2(400, 300);
this.point2 = new Phaser.Math.Vector2(550, 300);
this.interpolatedPoint = this.point1.clone().lerp(this.point2, this.t);
this.input.on('pointermove', pointer => {
this.point2.copy(pointer);
});
Как работает метод lerp
Метод .lerp(target, t) объекта Vector2 вычисляет линейную интерполяцию между текущей точкой и целевой точкой target. Параметр `t— это коэффициент интерполяции, обычно в диапазоне от 0 до 1. Когдаt = 0, результатом будет исходная точка; когдаt = 1` — целевая точка. Все промежуточные значения дают точку на прямой между ними.
Важно отметить, что оригинальный метод .lerp() изменяет текущий вектор. В нашем примере используется цепочка clone().lerp(...), чтобы сначала создать копию точки point1, а затем интерполировать её в сторону point2, не изменяя исходные данные.
// Прямое использование (изменяет вектор a)
a.lerp(b, 0.5);
// Безопасное использование с клонированием (как в примере)
let result = a.clone().lerp(b, 0.5);
Динамическое обновление и отрисовка
В методе update() происходит анимация. Сначала очищается холст от предыдущего кадра. Коэффициент `tциклически увеличивается от 0 до 1, создавая непрерывное движение промежуточной точки отpoint1кpoint2и обратно. На каждом кадре заново вычисляется позицияinterpolatedPoint`.
Затем отрисовываются три точки: две исходные — синим цветом, а интерполированная — зелёным. Также рисуется линия, соединяющая point1 и point2, чтобы визуализировать отрезок, по которому движется зелёная точка.
update ()
{
this.graphics.clear();
this.t = (this.t + 0.01) % 1;
this.interpolatedPoint = this.point1.clone().lerp(this.point2, this.t);
this.graphics.fillPointShape(this.point1, 20);
this.graphics.fillPointShape(this.point2, 20);
this.graphics.fillStyle(0x00aa00);
this.graphics.fillPointShape(this.interpolatedPoint, 20);
this.graphics.lineBetween(this.point1.x, this.point1.y, this.point2.x, this.point2.y);
}
Конфигурация игры
Стандартная конфигурация игры Phaser 3. Указываются размеры холста, тип рендерера (Phaser.AUTO выбирает между WebGL и Canvas), ID родительского HTML-элемента и класс основной сцены.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Линейная интерполяция с помощью Vector2.lerp() — это мощный и простой инструмент для создания плавного движения и расчёта промежуточных позиций в Phaser. Она лежит в основе многих игровых механик. Для экспериментов попробуйте: изменить закон изменения параметра `t` (например, использовать синусоиду для колебаний), применить интерполяцию к цветам или масштабу спрайтов, или создать цепочку из нескольких точек для движения по сложному маршруту.
