О чем этот пример
Создание плавных и визуально интересных траекторий движения — ключевой элемент геймдизайна. В этом примере мы разберем, как использовать объект `Phaser.Curves.Path` для построения сложного замкнутого пути, состоящего из двух соприкасающихся кругов, и как заставить объект бесконечно следовать по этому маршруту. Этот подход полезен для анимации патрулирования врагов, движения планет, элементов интерфейса или любых объектов, чей путь должен быть цикличным и геометрически точным.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
graphics;
path;
follower;
create ()
{
this.graphics = this.add.graphics();
this.follower = { t: 0, vec: new Phaser.Math.Vector2() };
this.path = new Phaser.Curves.Path(400, 300);
this.path.circleTo(100);
this.path.moveTo(400, 300);
// Rotate this circle so it completes the loop
this.path.circleTo(100, true, 180);
this.tweens.add({
targets: this.follower,
t: 1,
ease: 'Linear',
duration: 2000,
repeat: -1
});
}
update ()
{
this.graphics.clear();
this.graphics.lineStyle(2, 0xffffff, 1);
this.path.draw(this.graphics);
this.path.getPoint(this.follower.t, this.follower.vec);
this.graphics.fillStyle(0xff0000, 1);
this.graphics.fillCircle(this.follower.vec.x, this.follower.vec.y, 12);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Инициализация сцены и создание пути
В методе create() сцены происходит базовая настройка. Сначала мы создаем объект Graphics для визуального отображения пути на экране.
Затем определяется объект-последователь (follower). Это простой объект с двумя свойствами: `t(текущая позиция на кривой от 0 до 1) иvec` (вектор для хранения расчетных координат).
Далее создается сам путь (Path). Конструктор принимает начальные координаты.
this.graphics = this.add.graphics();
this.follower = { t: 0, vec: new Phaser.Math.Vector2() };
this.path = new Phaser.Curves.Path(400, 300);
Построение фигуры из двух кругов
Ключевая часть — построение сложной фигуры. Метод circleTo() объекта Path добавляет к пути эллиптическую кривую. Первый вызов рисует круг радиуса 100 пикселей, начиная от текущей точки пути (400, 300).
Затем moveTo() возвращает «перо» в исходную точку, не рисуя соединительную линию. Второй вызов circleTo() с параметром true (рисовать по часовой стрелке) и начальным углом 180 градусов создает второй круг, который начинается с противоположной стороны от первого, формируя фигуру в виде «восьмерки» или двойной петли.
this.path.circleTo(100);
this.path.moveTo(400, 300);
this.path.circleTo(100, true, 180);
Анимация движения по пути
Чтобы объект двигался по пути, используется система твинов Phaser. Мы создаем твин, который бесконечно (repeat: -1) и линейно (ease: 'Linear') изменяет свойство `tобъекта-последователя от 0 до 1 за 2 секунды (duration: 2000). Именно изменение значенияt` от начала (0) до конца (1) пути обеспечивает перемещение.
this.tweens.add({
targets: this.follower,
t: 1,
ease: 'Linear',
duration: 2000,
repeat: -1
});
Визуализация пути и объекта в реальном времени
В методе update() происходит отрисовка кадра. Сначала graphics.clear() стирает предыдущий кадр. Затем задается стиль линии и рисуется сам путь с помощью path.draw().
Сердцевина логики движения — вызов path.getPoint(this.follower.t, this.follower.vec). Этот метод вычисляет координаты (x, y) на кривой для текущего значения `tи записывает их в векторthis.follower.vec`.
Наконец, в этих вычисленных координатах рисуется красный круг, представляющий движущийся объект.
this.graphics.clear();
this.graphics.lineStyle(2, 0xffffff, 1);
this.path.draw(this.graphics);
this.path.getPoint(this.follower.t, this.follower.vec);
this.graphics.fillStyle(0xff0000, 1);
this.graphics.fillCircle(this.follower.vec.x, this.follower.vec.y, 12);
Что попробовать дальше
Объект Phaser.Curves.Path предоставляет мощный и гибкий инструмент для описания предопределенных траекторий. Комбинируя простые кривые, такие как circleTo(), ellipseTo() или splineTo(), и управляя «пером» с помощью moveTo(), можно создавать траектории любой сложности. Для экспериментов попробуйте: изменить радиус кругов, добавить третий сегмент пути, привязать к движению по пути не точку, а спрайт с физическим телом или изменить ease твина на 'Sine.easeInOut', чтобы скорость объекта менялась плавно.
