О чем этот пример
Создание десятков и сотен однотипных игровых объектов — частая задача в геймдеве. Добавлять каждый объект по отдельности через `this.add.image()` — утомительно и неэффективно. Phaser 3 предлагает элегантное решение: метод `this.add.group()`, который позволяет создавать и настраивать множество объектов сразу, используя конфигурационные объекты. Эта статья покажет, как с помощью одного вызова метода можно создать сложные сетки или группы спрайтов с разным поведением, что критически важно для создания частиц, врагов, плиток поля и других повторяющихся элементов.
Версия 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.spritesheet('diamonds', 'assets/sprites/diamonds32x24x5.png', { frameWidth: 32, frameHeight: 24 });
}
create ()
{
// We can pass in multiple config objects to a Group
// and it will create the children in turn.
const group = this.add.group([
{
key: 'diamonds',
frame: [ 0, 1, 2, 3, 4 ],
setXY:
{
x: 100,
y: 100,
stepX: 64,
stepY: 64
}
},
{
key: 'diamonds',
frame: [ 0, 1, 2, 3, 4 ],
setXY:
{
x: 356,
y: 100,
stepX: -64,
stepY: 64
}
}
]);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое Group и зачем она нужна
В Phaser Group — это не просто визуальный контейнер. Это полноценный менеджер для пула игровых объектов, который упрощает их создание, обновление и уничтожение. Группа позволяет обращаться с множеством объектов как с единым целым, что особенно полезно для физических тел, анимаций и массовых операций.
Ключевой метод this.add.group() может принимать не только общие настройки самой группы, но и массив конфигурационных объектов. Каждый элемент этого массива описывает набор однотипных объектов, которые нужно создать внутри этой группы. Это открывает путь для сложной инициализации в одном месте.
Разбор конфигурационного объекта
Каждый объект в массиве, передаваемом в add.group, определяет свойства для создаваемых спрайтов. Давайте разберем поля на примере из исходного кода.
Основные свойства:
* key: ключ загруженного спрайтшита или изображения.
* frame: массив индексов кадров из спрайтшита. Phaser создаст по одному спрайту для каждого указанного кадра.
* setXY: объект с настройками позиционирования создаваемых спрайтов.
{
key: 'diamonds',
frame: [ 0, 1, 2, 3, 4 ],
setXY: {
x: 100,
y: 100,
stepX: 64,
stepY: 64
}
}
В этом примере будет создано 5 спрайтов (по одному для каждого из пяти кадров [0,1,2,3,4] спрайтшита 'diamonds'). Первый спрайт появится в точке (100, 100). Свойства stepX и stepY задают шаг смещения для каждого последующего спрайта. Второй спрайт окажется в (164, 164), третий — в (228, 228) и так далее. Фактически, мы создаем диагональную линию из разноцветных бриллиантов.
Создание нескольких наборов в одной группе
Мощь этого подхода раскрывается, когда мы передаем в метод не один, а несколько конфигурационных объектов. Phaser обработает их последовательно, добавляя все созданные спрайты в одну и ту же группу.
Посмотрите на вторую конфигурацию из примера:
{
key: 'diamonds',
frame: [ 0, 1, 2, 3, 4 ],
setXY: {
x: 356,
y: 100,
stepX: -64,
stepY: 64
}
}
Здесь начальная точка другая (356, 100), а stepX имеет отрицательное значение. Это значит, что второй набор из пяти бриллиантов будет выстроен по диагонали в обратную сторону (смещение влево на каждом шаге). В результате одним вызовом this.add.group() мы создаем две независимые "линии" спрайтов с разной геометрией размещения, объединенные в одну логическую группу для удобства дальнейшего управления.
Практическое применение и расширение
Такой подход — это не просто синтаксический сахар. Он идеально подходит для создания игровых полей, рядов врагов, инвентаря или систем частиц, где объекты имеют общую текстуру, но различаются кадром анимации или позицией.
Вы можете комбинировать setXY с другими свойствами конфигурации, например, setScale или setAlpha, чтобы сразу задавать размер или прозрачность для целого набора объектов.
Представьте, что вам нужно создать стену из кирпичей с разными типами прочности (разные кадры спрайтшита) и сразу их позиционировать в виде сетки. Вместо двойного цикла for вы описываете это одним конфигурационным объектом.
// Пример создания сетки 3x3
const wallGroup = this.add.group([{
key: 'bricks',
frame: [0, 0, 0, 1, 1, 1, 2, 2, 2], // 9 кадров для 9 кирпичей
setXY: {
x: 200,
y: 100,
stepX: 70,
stepY: 40
}
}]);
Что попробовать дальше
Метод this.add.group() с передачей массива конфигов — это мощный инструмент для декларативного описания сложных наборов игровых объектов. Он делает код чище, читаемее и проще в поддержке, избавляя от многословных циклов создания.
Для экспериментов попробуйте:
1. Создать "галерею" спрайтов, где каждый новый ряд использует разные кадры спрайтшита.
2. Добавить в конфиг свойство setRotation с шагом, чтобы создать спираль или веер из объектов.
3. Скомбинировать этот подход с физикой, передав в конфиг свойство immovable: true, чтобы сразу создать статичную платформу из множества сегментов.
