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

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

Версия 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 points = [
            50, 300, 179, 449, 394, 498, 593, 455,
            701, 338, 692, 190, 603, 76, 423, 41,
            272, 78, 181, 186, 230, 328, 416, 395,
            565, 327, 550, 202, 467, 149, 355, 164,
            343, 254, 428, 303
        ];

        const curve = new Phaser.Curves.Spline(points);

        const graphics = this.add.graphics();

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

        curve.draw(graphics, 128);

        graphics.fillStyle(0x00ff00, 0.5);

        for (let i = 0; i < curve.points.length; i++)
        {
            graphics.fillCircle(curve.points[i].x, curve.points[i].y, 4);
        }

        const lemming = this.add.follower(curve, 50, 300, '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 3 для этого есть несколько классов. В примере используется Phaser.Curves.Spline, который создает плавную кривую, проходящую через заданные контрольные точки.

Массив points содержит пары координат X и Y. Это и есть наши контрольные точки, через которые будет проходить кривая.

const points = [
    50, 300, 179, 449, 394, 498, 593, 455,
    701, 338, 692, 190, 603, 76, 423, 41,
    272, 78, 181, 186, 230, 328, 416, 395,
    565, 327, 550, 202, 467, 149, 355, 164,
    343, 254, 428, 303
];

const curve = new Phaser.Curves.Spline(points);

Визуализация пути и точек

Для отладки и наглядности полезно видеть, как именно проходит наш путь. Для этого используется объект Graphics. Сначала мы задаем стиль линии и рисуем саму кривую с помощью метода curve.draw(). Аргумент 128 определяет количество сегментов для отрисовки — чем больше, тем глаже будет выглядеть кривая.

Затем зелеными кружочками отрисовываются сами контрольные точки, чтобы видеть, через какие координаты проходит сплайн.

const graphics = this.add.graphics();
graphics.lineStyle(1, 0xffffff, 0.5);
curve.draw(graphics, 128);
graphics.fillStyle(0x00ff00, 0.5);
for (let i = 0; i < curve.points.length; i++)
{
    graphics.fillCircle(curve.points[i].x, curve.points[i].y, 4);
}

Создание преследователя пути (Follower)

Ключевой объект для анимации движения по пути — это Follower. Он создается с помощью фабричного метода this.add.follower(). В него передается созданная ранее кривая (curve), начальные координаты (они должны совпадать с первой точкой кривой для плавного старта) и ключ текстуры спрайта.

Объект lemming теперь является контейнером, который "знает" о своем пути и может по нему двигаться.

const lemming = this.add.follower(curve, 50, 300, 'lemming');

Запуск движения с поворотом

Движение запускается методом lemming.startFollow(), который принимает объект конфигурации. Именно здесь настраивается поведение анимации.

- duration: Время в миллисекундах, за которое follower пройдет весь путь от начала до конца. - yoyo: Если true, объект, дойдя до конца пути, развернется и пойдет обратно. - repeat: Количество повторений (-1 для бесконечного повтора). - rotateToPath: Самая важная для нашей задачи настройка. При значении true спрайт будет автоматически поворачиваться так, чтобы его направление "взгляда" совпадало с касательной к пути в текущей точке. Это создает иллюзию, что лемминг поворачивает за поворотом дороги. - verticalAdjust: Опция, которая немного смещает точку вращения спрайта для более естественного выравнивания относительно пути.

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

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

Использование Phaser.Curves в паре с Follower и опцией rotateToPath — это мощный и лаконичный способ анимировать движение по сложным траекториям. Для экспериментов попробуйте изменить форму кривой, добавив или убрав контрольные точки. Поиграйте с параметрами duration и ease (не использован в примере) для изменения скорости и плавности хода. Можно создать несколько последовательных кривых и заставить follower переходить с одной на другую, создавая многоэтапные маршруты для патрулирования врагов или квестовых путешествий героя.