О чем этот пример
При разработке игр часто возникает задача заполнить сцену множеством однотипных объектов — монетами, врагами, частицами. Ручное создание каждого экземпляра через `add.image` или `add.sprite` быстро становится утомительным и непрактичным. Метод `createMultiple` для групп (Group) в Phaser решает эту проблему, позволяя генерировать десятки и сотни игровых объектов из одного или нескольких источников всего одним вызовом. В этой статье мы разберем продвинутое использование этого метода: как создавать объекты из нескольких текстур (spritesheet) одновременно, управлять кадрами анимации, повторять последовательности и применять случайное распределение. Это знание поможет вам эффективно наполнять миры ваших игр, будь то поле с разнообразной растительностью или груда драгоценных камней.
Версия 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 });
this.load.spritesheet('veg', 'assets/sprites/fruitnveg32wh37.png', { frameWidth: 32, frameHeight: 32 });
}
create ()
{
const group = this.add.group();
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4] });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4], repeat: 1 });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2], frameQuantity: 3 });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2], frameQuantity: 2, repeat: 1 });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4], randomKey: true });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4], randomFrame: true });
group.createMultiple({ key: [ 'diamonds', 'veg' ], frame: [ 0,1,2,3,4 ], randomFrame: true, frameQuantity: 2 });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4], randomKey: true, frameQuantity: 2 });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4], yoyo: true });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2], frameQuantity: 2, yoyo: true });
// group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3], repeat: 4, max: 15 });
Phaser.Actions.SetXY(group.getChildren(), 32, 100, 32);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Основа: Группы и createMultiple
Группа (Phaser.GameObjects.Group) — это контейнер для управления коллекцией игровых объектов. Она не отображается сама по себе, но упрощает создание, обновление и уничтожение множества объектов как единого целого.
Ключевой метод для массового создания — group.createMultiple(config). Он принимает объект конфигурации, который определяет, какие и сколько объектов нужно создать.
Давайте посмотрим на базовую структуру примера. В preload загружаются два спрайтшита, а в create создается пустая группа, которая затем заполняется.
const group = this.add.group();
group.createMultiple({ key: [ 'diamonds', 'veg' ], frame: [ 0,1,2,3,4 ], randomFrame: true, frameQuantity: 2 });
Работа с несколькими ключами (key)
Параметр key в конфиге может быть не только строкой, но и массивом строк. Это позволяет создавать объекты из разных текстур в рамках одной операции. Phaser будет перебирать элементы массива key в сочетании с массивом frame.
Например, простой вызов создаст объекты, последовательно используя оба спрайтшита и все указанные кадры.
group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4] });
В результате будет создано 10 объектов: 5 кадров из 'diamonds' и 5 кадров из 'veg'. Порядок создания: сначала все кадры из первого ключа, затем все кадры из второго.
Управление количеством: frameQuantity и repeat
Часто нужно создать не по одному объекту на кадр, а несколько. Для этого используется параметр frameQuantity. Он задает, сколько копий объекта создать для каждого сочетания ключа и кадра.
group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2], frameQuantity: 3 });
Здесь массив frame содержит 3 кадра. Умножаем на 2 ключа и на frameQuantity: 3. Итог: 2 * 3 * 3 = 18 созданных объектов.
Параметр repeat позволяет повторить всю последовательность создания заданное количество раз. Это полезно для создания сложных паттернов.
group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4], repeat: 1 });
Сначала создастся 5 объектов из 'diamonds', затем 5 из 'veg' (первый проход), а потом эта последовательность из 10 объектов повторится еще раз (второй проход due to repeat: 1). Всего 20 объектов.
Добавляем случайность: randomKey и randomFrame
Чтобы объекты выглядели разнообразнее и естественнее, их текстуры и кадры можно выбирать случайно. За это отвечают булевы параметры randomKey и randomFrame.
При randomKey: true для каждого создаваемого объекта ключ текстуры будет выбираться случайным образом из предоставленного массива.
group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3,4], randomKey: true });
При randomFrame: true для каждого объекта случайным образом будет выбран кадр из указанного массива. Это отлично подходит для создания неоднородных скоплений, например, кучи разных овощей или камней.
group.createMultiple({ key: [ 'diamonds', 'veg' ], frame: [ 0,1,2,3,4 ], randomFrame: true, frameQuantity: 2 });
Этот код из активной строки примера создаст 20 объектов (2 ключа * 5 кадров * frameQuantity: 2). Для каждого из этих 20 объектов кадр будет выбран случайно из пяти возможных.
Продвинутые паттерны: yoyo и max
Метод createMultiple поддерживает создание объектов по паттерну "йо-йо" (yoyo). Когда yoyo: true, последовательность кадров проигрывается вперед, а затем в обратном порядке.
group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2], frameQuantity: 2, yoyo: true });
Порядок создания кадров для каждого ключа будет: 0, 1, 2, 2, 1, 0. Это полезно для симметричных анимаций или расположений.
Параметр max устанавливает жесткое ограничение на общее количество создаваемых объектов. Даже если по логике конфига должно создаться больше объектов, генерация остановится при достижении лимита.
group.createMultiple({ key: ['diamonds', 'veg'], frame: [0,1,2,3], repeat: 4, max: 15 });
Без max было бы создано 32 объекта (2 ключа * 4 кадра * repeat+1=5 проходов). С параметром max: 15 создадутся только первые 15 объектов из этой последовательности.
Расположение созданных объектов
Метод createMultiple только создает объекты и добавляет их в группу, но не размещает на сцене. Все они оказываются в одной точке с координатами (0, 0). Для их расположения используется отдельный метод, например, Phaser.Actions.SetXY.
Phaser.Actions.SetXY(group.getChildren(), 32, 100, 32);
Этот вызов берет всех детей группы (массив объектов, полученный через group.getChildren()), и распределяет их по горизонтали, начиная с позиции (32, 100). Третий аргумент (32) — это шаг по оси X между каждым последующим объектом.
Таким образом, работа делится на два четких этапа: 1) Генерация пула объектов с нужными свойствами. 2) Их позиционирование и дальнейшая логика с помощью Phaser.Actions или вручную в цикле.
Что попробовать дальше
Метод createMultiple — это мощный инструмент для оптимизации и структурирования кода при создании множества однотипных объектов. Комбинируя массивы ключей, кадров, параметры количества, повторения и случайности, вы можете генерировать сложные и разнообразные наборы игровых элементов буквально в одну строку.
Для экспериментов попробуйте:
1. Создать "облако" частиц из 3-4 разных спрайтшитов, используя randomKey и randomFrame.
2. Смоделировать инвентарь или сетку предметов, используя frameQuantity и yoyo для симметричного отображения.
3. Сгенерировать волну врагов с ограничением по количеству через параметр max, чтобы не перегружать сцену.
