О чем этот пример
Создание плавного движения по кривой — стандартная задача в играх, но что если объекту нужно прервать маршрут и уйти в произвольную точку? Встроенный компонент 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 открывает тонкий контроль над анимацией следования. Вы можете не просто телепортировать объект, но и запустить новую анимацию, изменить его состояние или воспроизвести звук. Для экспериментов попробуйте
- Прервать движение по таймеру или клику мыши, вызвав
onCompleteдосрочно - После остановки твина запустить физическое тело шарика, создав эффект "сброса" с траектории
- Сделать цепочку путей, где завершение движения по одной кривой автоматически запускает движение по следующей
