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

Создание плавного движения по кривой — стандартная задача в играх, но что если объекту нужно прервать маршрут и уйти в произвольную точку? Встроенный компонент 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('ball', 'assets/sprites/shinyball.png');
    }

    create ()
    {
        const points = [ 50, 400, 200, 200, 350, 300, 500, 500, 700, 400 ];

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

        const graphics = this.add.graphics();

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

        curve.draw(graphics, 64);

        const ball = this.add.follower(curve, 50, 400, 'ball');

        ball.startFollow({
            duration: 4000,
            onComplete: () => {
                ball.pathTween.stop();
                ball.pathTween = null;
                ball.setPosition(100, 500);
            }
        });
    }
}

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

const game = new Phaser.Game(config);

Подготовка сцены и создание кривой

В методе preload загружается спрайт шарика. Основная логика находится в create. Сначала определяются опорные точки для кривой типа Spline. Этот тип кривой создает плавную линию, проходящую через все заданные точки, что идеально для органичных траекторий.

const points = [ 50, 400, 200, 200, 350, 300, 500, 500, 700, 400 ];
const curve = new Phaser.Curves.Spline(points);

Затем создается объект Graphics для визуализации пути прямо в игре. Это помогает на этапе отладки увидеть, по какой именно траектории будет двигаться объект.

const graphics = this.add.graphics();
graphics.lineStyle(1, 0xffffff, 1);
curve.draw(graphics, 64);

Создание последователя и запуск движения

Ключевой объект — последователь (Follower). Он создается с привязкой к кривой, стартовыми координатами и текстуре. Важно: стартовые координаты (50, 400) должны совпадать с первой точкой кривой, чтобы движение начиналось корректно.

const ball = this.add.follower(curve, 50, 400, 'ball');

Движение запускается методом startFollow. В конфигурации задается продолжительность анимации (4000 мс) и, что самое важное, функция обратного вызова onComplete, которая сработает по завершению пути.

Контроль завершения: прерываем твин и телепортируем объект

В колбэке onComplete происходит магия управления. Встроенный твин, отвечающий за движение по пути, хранится в свойстве объекта ball.pathTween. Чтобы полностью остановить анимацию и освободить ресурсы, этот твин нужно явно остановить и обнулить ссылку на него.

ball.pathTween.stop();
ball.pathTween = null;

Только после этого можно безопасно переместить объект в любую другую точку сцены, используя стандартный метод setPosition. В нашем примере шарик "уходит" с пути в координаты (100, 500).

ball.setPosition(100, 500);

Без остановки pathTween прямое изменение позиции может привести к конфликту управления между твином и вашим кодом.

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

Весь пример упакован в стандартную конфигурацию Phaser. Обратите внимание на параметр roundPixels: false — он отключает округление координат пикселей, что обеспечивает максимально плавное движение по кривой.

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

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

Использование колбэка onComplete и ручное управление pathTween открывает тонкий контроль над анимацией следования. Вы можете не просто телепортировать объект, но и запустить новую анимацию, изменить его состояние или воспроизвести звук. Для экспериментов попробуйте

  1. Прервать движение по таймеру или клику мыши, вызвав onComplete досрочно
  2. После остановки твина запустить физическое тело шарика, создав эффект "сброса" с траектории
  3. Сделать цепочку путей, где завершение движения по одной кривой автоматически запускает движение по следующей