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

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

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('lemming', 'assets/sprites/lemming.png');
    }

    create ()
    {
        const path1 = new Phaser.Curves.Path(50, 100).splineTo([ 164, 46, 274, 142, 412, 57, 522, 141, 664, 64 ]);
        const path2 = new Phaser.Curves.Path(100, 200).lineTo(500, 300);
        const path3 = new Phaser.Curves.Path(400, 400).circleTo(100);

        const graphics = this.add.graphics();

        graphics.lineStyle(1, 0xffffff, 1);

        path1.draw(graphics, 128);
        path2.draw(graphics, 128);
        path3.draw(graphics, 128);

        let current = 0;

        const lemming = this.add.follower(path1, 0, 0, 'lemming');

        lemming.startFollow({
            positionOnPath: true,
            duration: 3000,
            yoyo: true,
            repeat: -1,
            rotateToPath: true,
            verticalAdjust: true
        });

        this.input.on('pointerdown', () =>
        {

            current++;

            if (current === 3)
            {
                current = 0;
            }

            if (current === 0)
            {
                lemming.setPath(path1);
            }
            else if (current === 1)
            {
                lemming.setPath(path2);
            }
            else
            {
                lemming.setPath(path3);
            }

        });

    }
}

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

const game = new Phaser.Game(config);

Создание и визуализация путей

Перед тем как заставить объект двигаться, нужно определить сам путь. В Phaser 3 путь — это кривая, которая описывает траекторию. В примере создаются три разных типа путей с помощью класса Phaser.Curves.Path.

Первый путь — сплайн (сглаженная кривая), второй — прямая линия, третий — окружность. Для отладки и наглядности пути отрисовываются на сцене с помощью графического объекта.

const path1 = new Phaser.Curves.Path(50, 100).splineTo([ 164, 46, 274, 142, 412, 57, 522, 141, 664, 64 ]);
const path2 = new Phaser.Curves.Path(100, 200).lineTo(500, 300);
const path3 = new Phaser.Curves.Path(400, 400).circleTo(100);

const graphics = this.add.graphics();
graphics.lineStyle(1, 0xffffff, 1);
path1.draw(graphics, 128);
path2.draw(graphics, 128);
path3.draw(graphics, 128);

Настройка объекта-последователя (Follower)

Объект, который будет двигаться по пути, создается с помощью метода this.add.follower(). В качестве аргументов передается начальный путь, стартовые координаты (они будут проигнорированы, так как используется positionOnPath: true) и ключ текстуры.

Запуск движения осуществляется методом startFollow(), который принимает объект конфигурации. Здесь задается длительность прохождения пути, флаги повтора, движение «туда-обратно» (yoyo), а также важные опции вроде поворота спрайта по направлению пути.

const lemming = this.add.follower(path1, 0, 0, 'lemming');
lemming.startFollow({
    positionOnPath: true,
    duration: 3000,
    yoyo: true,
    repeat: -1,
    rotateToPath: true,
    verticalAdjust: true
});

Параметр positionOnPath: true указывает, что объект должен разместиться в начале пути, а не в переданных координатах (0,0). rotateToPath автоматически поворачивает спрайт по касательной к траектории, что критично для транспортных средств или персонажей.

Динамическое переключение пути по клику

Самая важная часть примера — возможность сменить путь у движущегося объекта «на лету». Для этого используется метод setPath(), который переназначает текущий путь follower'а.

В примере обработчик клика мыши перебирает три заранее созданных пути по кругу. При каждом клике увеличивается счетчик, и в зависимости от его значения объекту lemming назначается новый путь. Текущая позиция и прогресс движения сохраняются.

let current = 0;
this.input.on('pointerdown', () => {
    current++;
    if (current === 3) {
        current = 0;
    }
    if (current === 0) {
        lemming.setPath(path1);
    }
    else if (current === 1) {
        lemming.setPath(path2);
    }
    else {
        lemming.setPath(path3);
    }
});

Метод setPath() автоматически адаптирует объект к новому маршруту, продолжая движение с текущей точки. Это происходит без сброса анимации или видимых рывков.

Конфигурация игры и сцены

Как и в любом проекте на Phaser 3, необходима базовая конфигурация игры. В объекте config задаются размеры холста, цвет фона, элемент-контейнер и стартовая сцена.

Сцена Example расширяет Phaser.Scene и содержит методы preload() для загрузки ассетов и create() для инициализации логики.

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

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

Использование Follower и метода setPath() открывает широкие возможности для создания динамичных и отзывчивых игровых механик. Вы можете реализовать систему путевых точек для ИИ, интерактивные тренажеры или сложные анимационные последовательности. Для экспериментов попробуйте: 1. Изменять параметры пути (скорость, кривизну) в реальном времени. 2. Создавать пути на основе данных, введенных игроком. 3. Комбинировать с физикой Phaser, чтобы объект переключался с пути на свободное движение. 4. Использовать события onComplete для создания цепочек перемещений.