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

Движение объектов по заданным траекториям — одна из ключевых механик в играх. Использование системы Path Follower в Phaser позволяет создавать сложные, плавные и повторяющиеся пути для спрайтов без написания сложной логики вручную. Этот подход идеально подходит для создания патрулирующих врагов, летящих снарядов, платформ-лифтеров или декоративных анимированных элементов. В статье мы разберем пример, где спрайт движется по составному пути, состоящему из сплайнов, линий, эллипсов и кривых Безье.

Версия 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 path = new Phaser.Curves.Path(50, 500);

        path.splineTo([ 164, 446, 274, 542, 412, 457, 522, 541, 664, 464 ]);
        path.lineTo(700, 300);
        path.lineTo(600, 350);
        path.ellipseTo(200, 100, 100, 250, false, 0);
        path.cubicBezierTo(222, 119, 308, 107, 208, 368);
        path.ellipseTo(60, 60, 0, 360, true);

        const graphics = this.add.graphics();

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

        path.draw(graphics, 128);

        const lemming = this.add.follower(path, 50, 500, 'lemming');

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

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

const game = new Phaser.Game(config);

Создание и определение пути (Path)

В Phaser путь (Phaser.Curves.Path) представляет собой последовательность соединенных кривых. Вы создаете путь, указывая начальную точку, а затем добавляете к нему различные сегменты.

В нашем примере путь начинается в точке (50, 500). Метод splineTo создает плавную кривую (сплайн), проходящую через массив контрольных точек. Затем lineTo добавляет прямые отрезки. Методы ellipseTo и cubicBezierTo позволяют рисовать эллипсы и кубические кривые Безье соответственно.

Для визуализации пути в целях отладки мы создаем объект Graphics и рисуем на нем наш путь с помощью метода draw.

const path = new Phaser.Curves.Path(50, 500);

path.splineTo([ 164, 446, 274, 542, 412, 457, 522, 541, 664, 464 ]);
path.lineTo(700, 300);
path.lineTo(600, 350);
path.ellipseTo(200, 100, 100, 250, false, 0);
path.cubicBezierTo(222, 119, 308, 107, 208, 368);
path.ellipseTo(60, 60, 0, 360, true);

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

Настройка следящего объекта (Follower)

Чтобы заставить спрайт следовать по созданному пути, используется объект Follower. Он создается через this.add.follower(), куда передаются сам путь, начальные координаты (которые должны совпадать с началом пути) и ключ текстуры.

const lemming = this.add.follower(path, 50, 500, 'lemming');

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

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

- duration: Время в миллисекундах, за которое объект пройдет весь путь от начала до конца. - yoyo: Если true, объект, дойдя до конца пути, развернется и пойдет обратно. - repeat: Количество повторений. Значение -1 означает бесконечное повторение. - rotateToPath: Автоматически поворачивает спрайт так, чтобы его передняя часть была направлена по касательной к траектории движения. Критически важно для реалистичного движения машин, самолетов или персонажей. - verticalAdjust: Небольшая коррекция позиции спрайта по вертикали для более точного совмещения с линией пути.

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

Для запуска примера необходимо создать стандартную конфигурацию игры Phaser (Phaser.Game). В ней указывается тип рендерера, размеры холста, цвет фона и корневой класс сцены.

Ключевой элемент — класс Example, расширяющий Phaser.Scene. В нем реализованы два основных метода жизненного цикла: 1. preload(): Здесь загружаются необходимые ассеты (в нашем случае — изображение спрайта 'lemming'). Базовый URL упрощает загрузку из репозитория с примерами. 2. create(): В этом методе, выполняемом один раз после загрузки ресурсов, происходит основная логика: создание пути, его отрисовка и настройка следящего объекта.

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

const game = new Phaser.Game(config);

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

Система Path Follower в Phaser предоставляет мощный и гибкий инструмент для анимации движения по сложным траекториям. Всего несколькими строками кода можно создать циклическое, плавное и визуально привлекательное перемещение объектов. **Идеи для экспериментов:** 1. Измените параметры ellipseTo и cubicBezierTo, чтобы создавать более замысловатые петли и виражи. 2. Попробуйте создать несколько объектов-follower на одном пути с разной скоростью (duration) или задержкой перед стартом. 3. Используйте событие 'complete' у объекта lemming, чтобы запускать определенные действия (например, атаку или смену анимации) в момент достижения конца пути. 4. Сделайте путь динамическим: модифицируйте контрольные точки пути path.curves[i].points во время выполнения игры в ответ на действия игрока.