О чем этот пример

Создание плавного движения объектов по заданным маршрутам — ключевая задача в игровой разработке. В Phaser для этого существует мощный инструмент — система `Curves`. В этой статье мы разберем, как создать составной путь из нескольких кривых, визуализировать его и анимировать движение объекта (фолловера) по этому пути с помощью твинов. Этот подход идеально подходит для создания патрульных путей врагов, траекторий снарядов или сложных анимаций интерфейса.

Версия 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() };

        //  The curves do not have to be joined
        const line1 = new Phaser.Curves.Line([ 100, 100, 500, 200 ]);
        const line2 = new Phaser.Curves.Line([ 200, 300, 600, 500 ]);

        this.path = this.add.path();

        // path = new Phaser.Curves.Path();

        this.path.add(line1);
        this.path.add(line2);

        this.tweens.add({
            targets: this.follower,
            t: 1,
            ease: 'Linear',
            duration: 4000,
            yoyo: true,
            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.fillRect(this.follower.vec.x - 8, this.follower.vec.y - 8, 16, 16);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Создание сцены и подготовка объектов

Вся логика примера заключена в классе сцены, унаследованном от Phaser.Scene. В нем объявляются три основных свойства: graphics для рисования, path для хранения пути и follower — объект, который будет двигаться.

class Example extends Phaser.Scene
{
    graphics;
    path;
    follower;

В методе create() инициализируются эти объекты. this.graphics создается как холст для рисования линий. this.follower — это обычный JavaScript-объект, который будет хранить текущую позицию на пути (от 0 до 1) и вектор для вычисления координат.

create ()
{
    this.graphics = this.add.graphics();
    this.follower = { t: 0, vec: new Phaser.Math.Vector2() };

Конструирование пути из кривых

Путь (Path) в Phaser — это контейнер, который может содержать одну или несколько кривых (Curves), соединенных последовательно. В примере создаются две простейшие кривые — прямые линии (Phaser.Curves.Line).

const line1 = new Phaser.Curves.Line([ 100, 100, 500, 200 ]);
const line2 = new Phaser.Curves.Line([ 200, 300, 600, 500 ]);

Каждый массив определяет начальную и конечную точку линии [x1, y1, x2, y2]. Обратите внимание: конец line1 и начало line2 не совпадают, что допустимо — путь может состоять из разрозненных сегментов.

Далее создается объект Path. Важно использовать фабричный метод сцены this.add.path(), чтобы путь был корректно интегрирован в систему обновления сцены, хотя можно создать его и напрямую через new Phaser.Curves.Path().

this.path = this.add.path();
// path = new Phaser.Curves.Path();
this.path.add(line1);
this.path.add(line2);

Кривые добавляются в путь в порядке их следования.

Анимация движения с помощью Tween

Чтобы заставить фолловера двигаться по пути, нужно плавно менять его свойство `t` от 0 (начало пути) до 1 (конец пути). Для этого идеально подходит система твинов Phaser.

this.tweens.add({
    targets: this.follower,
    t: 1,
    ease: 'Linear',
    duration: 4000,
    yoyo: true,
    repeat: -1
});

Здесь создается твин, который: * targets: Целевой объект — наш this.follower. * t: 1: Конечное значение свойства `t`. * ease: 'Linear': Используется линейная интерполяция, чтобы движение по пути было равномерным. * duration: 4000: Длительность анимации в миллисекундах. * yoyo: true: После достижения конца, анимация проиграется в обратном порядке. * repeat: -1: Анимация будет повторяться бесконечно.

Визуализация пути и объекта в Update

Метод update() вызывается каждый кадр. Здесь происходит отрисовка текущего состояния: пути и фолловера.

Сначала очищается холст graphics от предыдущего кадра и задается стиль линии.

update ()
{
    this.graphics.clear();
    this.graphics.lineStyle(2, 0xffffff, 1);

Затем рисуется сам путь, используя метод draw.

this.path.draw(this.graphics);

Самый важный шаг — получение текущих мировых координат точки на пути, соответствующей значению this.follower.t. Метод getPoint вычисляет координаты и записывает их в переданный вектор this.follower.vec.

this.path.getPoint(this.follower.t, this.follower.vec);

Наконец, в этих координатах рисуется красный квадратик, представляющий фолловера.

this.graphics.fillStyle(0xff0000, 1);
this.graphics.fillRect(this.follower.vec.x - 8, this.follower.vec.y - 8, 16, 16);

Настройка и запуск игры

Конфигурационный объект игры задает базовые параметры: рендерер, размер холста, цвет фона и корневую сцену.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

Запуск игры осуществляется созданием экземпляра Phaser.Game с этой конфигурацией.

const game = new Phaser.Game(config);

Что попробовать дальше

Используя связку Path, Curves и Tween, вы можете легко создавать сложные, нелинейные траектории движения в своих играх на Phaser. Для экспериментов попробуйте: заменить Line на Spline или Ellipse для плавных изгибов; сделать путь замкнутым, чтобы объект ходил по кругу; привязать к фолловеру не графический примитив, а спрайт с текстурой и анимацией; или управлять значением `tне твином, а вручную вupdate` в ответ на действия игрока.