О чем этот пример
При разработке игр часто возникает задача расположить множество однотипных объектов (например, анимированных спрайтов) в аккуратные ряды или сетки. Вручную задавать координаты для каждого — утомительно и неэффективно. Phaser предоставляет для этого удобный инструмент — `Phaser.Actions.GridAlign`. Эта статья покажет, как с помощью одного вызова метода превратить хаотичную кучу спрайтов в упорядоченную анимационную сетку, что особенно полезно для создания интерфейсов, меню выбора персонажей или фоновых декораций.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/deepblue.png');
this.load.spritesheet('sotb', 'assets/animations/sotb-64x112x11.png', { frameWidth: 64, frameHeight: 112 });
}
create ()
{
this.add.image(400, 300, 'bg');
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('sotb'),
frameRate: 16,
repeat: -1
});
const sprites = [];
for (var i = 0; i < 60; i++)
{
sprites.push(this.add.sprite(0, 0, 'sotb').play('walk'));
}
// The sprites are 64x112 in size
// Let's lay them out in a grid 12 sprites wide, by as many tall as we have sprites in the array for
Phaser.Actions.GridAlign(sprites, {
width: 12,
cellWidth: 64,
cellHeight: 120,
x: 16,
y: 4
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
В методе preload мы загружаем два ресурса: фоновое изображение ('bg') и спрайтшит ('sotb'). Спрайтшит — это изображение, содержащее несколько кадров анимации в одной текстуре. При загрузке мы указываем его ключ, путь и размер одного кадра (64x112 пикселя). Это необходимо для корректного создания анимации.
this.load.image('bg', 'assets/skies/deepblue.png');
this.load.spritesheet('sotb', 'assets/animations/sotb-64x112x11.png', { frameWidth: 64, frameHeight: 112 });
Создание анимации и массива спрайтов
В методе create сначала добавляется фон. Затем создаётся анимация с ключом 'walk'. Функция this.anims.generateFrameNumbers('sotb') автоматически генерирует массив кадров из всего загруженного спрайтшита. Параметр repeat: -1 задаёт бесконечное повторение анимации.
Далее в цикле создаётся 60 спрайтов. Каждый из них использует текстуру 'sotb', добавляется в сцену в точке (0, 0) и сразу начинает проигрывать анимацию 'walk'. Все созданные спрайты сохраняются в массив sprites.
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('sotb'),
frameRate: 16,
repeat: -1
});
const sprites = [];
for (var i = 0; i < 60; i++)
{
sprites.push(this.add.sprite(0, 0, 'sotb').play('walk'));
}
Магия выравнивания: Phaser.Actions.GridAlign
Вся логика упорядочивания заключена в один вызов Phaser.Actions.GridAlign. Этот метод принимает массив игровых объектов (в нашем случае — спрайтов) и объект конфигурации. Он перебирает массив и расставляет объекты в сетке согласно заданным правилам.
Ключевые параметры конфига:
* width: 12 — количество столбцов в сетке. Всего 60 спрайтов, поэтому получится 5 строк (60 / 12).
* cellWidth: 64 и cellHeight: 120 — размер ячейки сетки. Ширина равна ширине спрайта (64), а высота (120) чуть больше высоты спрайта (112), чтобы создать отступ между строками.
* x: 16 и y: 4 — смещение всей сетки от левого верхнего угла сцены. Это позволяет создать поля.
Метод автоматически рассчитывает координаты для каждого спрайта и присваивает их его свойству position.
Phaser.Actions.GridAlign(sprites, {
width: 12,
cellWidth: 64,
cellHeight: 120,
x: 16,
y: 4
});
Настройка игры (конфиг)
Объект config определяет базовые настройки игрового экземпляра Phaser. Здесь задаётся тип рендерера (Phaser.AUTO), размеры холста (800x600), цвет фона (на случай, если фон не загрузится), ID HTML-элемента для встраивания и стартовая сцена (Example). В конце конфигурация передаётся в конструктор new Phaser.Game(config) для запуска игры.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Phaser.Actions.GridAlign — это мощный и лаконичный способ организовать множество игровых объектов в структурированную композицию. Он избавляет от написания громоздких циклов с расчётом координат. Для экспериментов попробуйте: изменить параметры width, cellHeight или `x,y; использовать другой метод из семействаActions, например,PlaceOnLineилиPlaceOnCircle; или применитьGridAlign` не к спрайтам, а к контейнерам с интерактивными элементами для построения сложных меню.
