О чем этот пример
Создание плавных и сложных траекторий движения — ключевой навык для оживления игрового мира. В этом руководстве мы разберем пример из официальной документации Phaser, где спрайт лемминга движется по заданной сплайн-кривой. Вы научитесь создавать кривые, визуализировать их, а главное — управлять движением объекта с помощью мощного компонента Follower, включая контроль над стартовой позицией, повторами и реакцией на действия игрока. Этот подход идеально подходит для создания патрульных путей врагов, траекторий снарядов или кат-сцен.
Версия 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 = [];
points.push(new Phaser.Math.Vector2(50, 400));
points.push(new Phaser.Math.Vector2(200, 200));
points.push(new Phaser.Math.Vector2(350, 300));
points.push(new Phaser.Math.Vector2(500, 500));
points.push(new Phaser.Math.Vector2(700, 400));
const curve = new Phaser.Curves.Spline(points);
const graphics = this.add.graphics();
graphics.lineStyle(1, 0xffffff, 1);
curve.draw(graphics, 64);
graphics.fillStyle(0x00ff00, 1);
for (let i = 0; i < points.length; i++)
{
graphics.fillCircle(points[i].x, points[i].y, 4);
}
const lemming = this.add.follower(curve, 50, 400, 'lemming');
lemming.startFollow({
duration: 6000,
yoyo: true,
repeat: -1,
rotateToPath: true,
startAt: 0.5
});
this.input.on('pointerdown', () =>
{
if (lemming.isFollowing())
{
lemming.pauseFollow();
}
else
{
lemming.resumeFollow();
}
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание кривой
Вся логика примера находится в методе create() нашей сцены. Первым делом мы определяем набор точек, которые станут опорными для нашей кривой. Для этого используется класс Phaser.Math.Vector2.
const points = [];
points.push(new Phaser.Math.Vector2(50, 400));
points.push(new Phaser.Math.Vector2(200, 200));
points.push(new Phaser.Math.Vector2(350, 300));
points.push(new Phaser.Math.Vector2(500, 500));
points.push(new Phaser.Math.Vector2(700, 400));
Затем эти точки передаются конструктору Phaser.Curves.Spline, который создает плавную кривую, проходящую через все заданные точки. Это гораздо более гибкий инструмент, чем простая ломаная линия.
const curve = new Phaser.Curves.Spline(points);
Визуализация пути
Чтобы видеть созданный путь на экране, мы используем объект Graphics. Это встроенный в Phaser инструмент для программного рисования.
Сначала задаем стиль линии: толщина 1 пиксель, белый цвет (0xffffff), полная непрозрачность (альфа = 1). Затем метод curve.draw() отрисовывает саму кривую на нашем графическом объекте, используя 64 отрезка для сглаживания.
const graphics = this.add.graphics();
graphics.lineStyle(1, 0xffffff, 1);
curve.draw(graphics, 64);
Для наглядности также отрисуем зеленые точки в местах опорных векторов, которые мы задали изначально.
graphics.fillStyle(0x00ff00, 1);
for (let i = 0; i < points.length; i++)
{
graphics.fillCircle(points[i].x, points[i].y, 4);
}
Создание и запуск следящего объекта (Follower)
Самый важный объект в этом примере — follower. Он создается с помощью метода this.add.follower(), который принимает саму кривую, начальные координаты (они будут проигнорированы, так как позиция определяется кривой) и ключ текстуры спрайта.
const lemming = this.add.follower(curve, 50, 400, 'lemming');
Движение запускается методом startFollow(), который принимает объект конфигурации. Вот что значат его ключевые параметры:
* duration: Время в миллисекундах, за которое объект пройдет весь путь от начала до конца.
* yoyo: Если true, объект, дойдя до конца пути, развернется и пойдет обратно.
* repeat: Количество повторений (-1 для бесконечного цикла).
* rotateToPath: Автоматически поворачивает спрайт по направлению движения.
* startAt: Самый интересный параметр. Он определяет точку старта на кривой как долю от ее общей длины. Значение 0.5 означает, что лемминг начнет движение ровно с середины пути.
lemming.startFollow({
duration: 6000,
yoyo: true,
repeat: -1,
rotateToPath: true,
startAt: 0.5
});
Интерактивность: управление движением
Пример добавляет простую интерактивность. При клике мышью мы проверяем, находится ли follower в состоянии следования, с помощью метода isFollowing(). В зависимости от результата мы либо приостанавливаем движение методом pauseFollow(), либо возобновляем его методом resumeFollow(). Это демонстрирует, как легко можно интегрировать логику управления в геймплей.
this.input.on('pointerdown', () => {
if (lemming.isFollowing())
{
lemming.pauseFollow();
}
else
{
lemming.resumeFollow();
}
});
Что попробовать дальше
Компонент Follower в Phaser 3 — это мощный и удобный инструмент для декларативного описания сложного движения. Используя кривые и гибкие настройки анимации, вы можете создавать динамичные сцены буквально несколькими строками кода. Для экспериментов попробуйте: изменить тип кривой на Phaser.Curves.Path или Phaser.Curves.Ellipse; анимировать startAt для эффекта телепортации объекта по пути; привязать к движению по кривой не спрайт, а камеру для создания эффектных пролетов; или использовать несколько последовательных followers для построения целых анимированных цепочек.
