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

Создание плавных и сложных путей движения — ключевой навык для оживления игрового мира. Встроенный в 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() };

        //  Path starts at 100x100
        this.path = new Phaser.Curves.Path(50, 500);

        this.path.lineTo(150, 300);

        // xRadius, yRadius, startAngle, endAngle, clockwise, rotation
        this.path.ellipseTo(200, 100, 100, 300, false, 45);

        this.path.ellipseTo(200, 100, 100, 300, true);

        this.path.ellipseTo(60);

        this.tweens.add({
            targets: this.follower,
            t: 1,
            ease: 'Sine.easeInOut',
            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.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 — это простой контейнер для хранения текущей позиции на кривой (от 0 до 1) и вектора для вычисленных координат.

Кривая Path создается с начальной точки. Все последующие сегменты будут добавляться относительно этой точки.

this.graphics = this.add.graphics();
this.follower = { t: 0, vec: new Phaser.Math.Vector2() };
this.path = new Phaser.Curves.Path(50, 500);

Построение составного пути: линия и эллипсы

Мощь Curves.Path заключается в цепочке вызовов. Мы последовательно добавляем сегменты, формируя единый путь. Первым добавляется прямой отрезок от начальной точки до указанных координат.

Затем добавляются три эллиптических сегмента с помощью метода ellipseTo. Его параметры позволяют гибко управлять формой и ориентацией эллипса.

this.path.lineTo(150, 300);
// xRadius, yRadius, startAngle, endAngle, clockwise, rotation
this.path.ellipseTo(200, 100, 100, 300, false, 45);
this.path.ellipseTo(200, 100, 100, 300, true);
this.path.ellipseTo(60);

Первый ellipseTo рисует дугу эллипса с радиусами 200 и 100, от угла 100 до 300 градусов, против часовой стрелки (false), повернутую на 45 градусов. Второй вызов, с параметром true, рисует дугу по часовой стрелке с теми же радиусами и углами. Третий высов демонстрирует краткую форму записи, где задается только радиус по оси Y (60), а остальные параметры берутся по умолчанию.

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

Чтобы заставить точку двигаться по пути, мы анимируем свойство `tобъектаfollowerот 0 до 1. Значениеt=0соответствует началу пути,t=1— его концу. Tween создается с эффектомSine.easeInOutдля плавности, длительностью 4 секунды. Параметрыyoyo: trueиrepeat: -1` заставляют анимацию автоматически проигрываться вперед-назад бесконечно.

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

Отрисовка пути и объекта в реальном времени

В методе update() происходит визуализация. Сначала графический контекст очищается, и задается стиль линии для отрисовки контура пути.

Метод path.draw(graphics) рисует всю составную кривую на экране.

Затем ключевой метод path.getPoint(t, vector) вычисляет точку на кривой, соответствующую текущему значению follower.t, и записывает её координаты в вектор 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 — это мощный и простой инструмент для описания нелинейных траекторий. Комбинируя линии, эллипсы, сплайны и другие кривые, вы можете создавать маршруты любой сложности для движения врагов, кат-сцен или камеры. Для экспериментов попробуйте заменить красный круг на спрайт игрока, изменить параметры эллипсов (радиусы, углы, вращение) или добавить новые сегменты, например, сплайн splineTo. Это откроет путь к созданию динамичного и визуально интересного геймплея.