О чем этот пример
При создании игр часто возникает задача динамического размещения объектов по заданной геометрической форме. В Phaser для этого есть мощное средство — `Phaser.Actions.PlaceOnRectangle`. Эта статья покажет, как использовать этот метод для создания плавной анимации, где спрайты следуют за изменяющимся прямоугольником, и как управлять смещением для эффекта 'бегущей строки'. Этот приём полезен для создания интерактивных меню, орбит, патрульных путей или просто визуально привлекательных эффектов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
this.i = 0;
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.spritesheet('balls', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
}
create ()
{
this.rect = new Phaser.Geom.Rectangle(64, 32, 100, 512);
this.group = this.add.group({ key: 'balls', frame: [0,1,2,3,4,5], frameQuantity: 10 });
this.tweens.add({
targets: this.rect,
x: 200,
y: 200,
width: 512,
height: 100,
delay: 2000,
duration: 3000,
ease: 'Sine.easeInOut',
repeat: -1,
yoyo: true
});
}
update ()
{
Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), this.rect, this.i);
this.i++;
if (this.i === this.group.length)
{
this.i = 0;
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и данных
В примере создаётся простая сцена. В preload загружается спрайтшит с шариками. Ключевые объекты создаются в методе create.
Во-первых, определяется прямоугольник this.rect, который будет служить траекторией для размещения объектов. Его начальные координаты и размеры задаются конструктором.
this.rect = new Phaser.Geom.Rectangle(64, 32, 100, 512);
Во-вторых, создаётся группа спрайтов this.group. Группа автоматически создаёт 10 спрайтов (frameQuantity) для каждого из шести кадров (frame) из спрайтшита 'balls'.
this.group = this.add.group({ key: 'balls', frame: [0,1,2,3,4,5], frameQuantity: 10 });
Также в constructor инициализируется счётчик this.i, который будет использоваться для смещения.
constructor ()
{
super();
this.i = 0;
}
Анимация прямоугольника-траектории
Чтобы визуализация была наглядной, прямоугольник не статичен. На него навешивается твин, который циклично меняет его положение и размеры.
this.tweens.add({
targets: this.rect,
x: 200,
y: 200,
width: 512,
height: 100,
delay: 2000,
duration: 3000,
ease: 'Sine.easeInOut',
repeat: -1,
yoyo: true
});
Этот код анимирует свойства `x,y,widthиheightобъектаthis.rect`. Твин стартует с задержкой в 2 секунды, длится 3 секунды, использует плавную эasing-функцию и повторяется бесконечно с эффектом 'йо-йо' (движение вперёд и назад). Таким образом, форма и положение траектории постоянно меняются.
Динамическое размещение объектов в update
Сердце примера — метод update, который вызывается на каждом кадре. Здесь происходит магия размещения.
Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), this.rect, this.i);
Метод PlaceOnRectangle принимает три аргумента:
1. Массив объектов для размещения (все дети группы, полученные через getChildren()).
2. Прямоугольник (Phaser.Geom.Rectangle), по периметру которого будут расположены объекты.
3. Смещение (this.i). Это целочисленное значение, определяющее, с какой позиции на периметре прямоугольника начнётся расстановка.
После каждого вызова индекс смещения увеличивается, а когда достигает количества объектов в группе — сбрасывается в ноль. Это создаёт эффект циклического сдвига всех объектов по траектории.
this.i++;
if (this.i === this.group.length)
{
this.i = 0;
}
Поскольку update выполняется постоянно, а прямоугольник анимирован твином, спрайты плавно 'едут' по меняющейся замкнутой фигуре.
Инициализация игры (конфигурация)
Запуск игры происходит стандартным для Phaser 3 образом. Конфигурационный объект задаёт тип рендерера, размеры холста, родительский HTML-элемент и нашу сцену Example.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Phaser.Actions.PlaceOnRectangle — это простой, но мощный инструмент для расположения объектов по контуру. В связке с твинами и логикой обновления он позволяет создавать сложные динамические паттерны буквально в несколько строк кода.
**Идеи для экспериментов:**
1. Замените прямоугольник на круг (Phaser.Geom.Circle) и используйте PlaceOnCircle.
2. Изменяйте смещение this.i не на 1, а на другое число, или привяжите его к времени для контроля скорости 'прокрутки'.
3. Используйте разные easing-функции для твина прямоугольника, чтобы получить более резкие или причудливые трансформации траектории.
4. Добавьте физические тела к объектам в группе и посмотрите, как они будут взаимодействовать, двигаясь по заданному пути.
