О чем этот пример

При создании игр часто требуется добавить на сцену множество однотипных объектов: монеты, враги, частицы. Ручное создание каждого из них через `add.image` или `add.sprite` утомительно и приводит к громоздкому коду. Метод `createMultiple` класса `Group` в Phaser решает эту задачу элегантно, позволяя создавать десятки и сотни игровых объектов одной строкой, с тонкой настройкой их внешнего вида и количества. Эта статья покажет, как использовать этот мощный инструмент для оптимизации вашего кода и быстрого наполнения игрового мира.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    group;

    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 ()
    {
        this.group = this.add.group();

        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4] });
        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], repeat: 1 });
        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], frameQuantity: 4 });
        this.group.createMultiple({ key: 'diamonds', frame: [ 0,1,2,3,4 ], frameQuantity: 2, repeat: 1 });

        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], randomFrame: true });
        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], randomFrame: true, frameQuantity: 2 });
        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], yoyo: true });
        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], frameQuantity: 2, yoyo: true });
        // group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], repeat: 4, max: 12 });

        Phaser.Actions.SetXY(this.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);

Что такое Group и зачем нужен createMultiple

Group в Phaser — это контейнер для управления коллекциями игровых объектов. Он не отрисовывается сам по себе, но предоставляет удобные методы для работы со всеми объектами внутри него, такие как массовое обновление позиций или получение списка детей.

Метод createMultiple — это фабрика, которая создает несколько спрайтов (или других игровых объектов) и автоматически добавляет их в группу. Основное преимущество — декларативность: вы описываете, *что* хотите создать (ключ текстуры, кадры анимации, количество), а не прописываете циклы вручную.

В примере из исходника создается группа this.group, а затем одним вызовом заполняется спрайтами алмазов.

Разбор базового вызова и параметров

Давайте разберем рабочий вызов из примера, раскомментированный по умолчанию:

this.group.createMultiple({ key: 'diamonds', frame: [ 0,1,2,3,4 ], frameQuantity: 2, repeat: 1 });

Этот вызов создает несколько спрайтов. Разберем параметры объекта конфигурации: - key: 'diamonds': Ключ загруженного спрайтшита. - frame: [0,1,2,3,4]: Массив индексов кадров (фреймов) из спрайтшита. Phaser будет использовать эти кадры для создаваемых спрайтов. - frameQuantity: 2: Количество спрайтов, создаваемых для *каждого* кадра из массива frame. Для кадра 0 создастся 2 спрайта, для кадра 1 — еще 2, и так далее. - repeat: 1: Количество дополнительных повторений всего процесса создания. При repeat: 1 процесс (создание frameQuantity спрайтов для каждого кадра) выполнится дважды (исходный проход + одно повторение).

**Итоговое количество объектов:** 5 кадров * 2 спрайта на кадр * (1 + 1 повторение) = 20 спрайтов. Все они автоматически добавлены в this.group.

Следующая строка в create использует Phaser.Actions.SetXY для упорядоченного размещения всех этих спрайтов на экране.

Полезные вариации: randomFrame, yoyo и max

В исходном коде закомментированы другие практические варианты использования createMultiple. Рассмотрим их логику.

**Случайный кадр (randomFrame):**

// Создает спрайты, для каждого случайно выбирая кадр из массива [0,1,2,3,4]
this.group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], randomFrame: true });

Это отлично подходит для создания разнообразных врагов, ландшафта или предметов коллекций, где нужна визуальная вариативность.

**Чередование порядка (yoyo):**

// Кадры будут применены в порядке 0,1,2,3,4, а затем в обратном порядке 3,2,1,0 и так далее.
this.group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], frameQuantity: 2, yoyo: true });

Параметр yoyo меняет направление перебора массива кадров при каждом повторении, создавая более симметричные и визуально приятные последовательности.

**Ограничение количества (max):**

// Процесс создания остановится, как только в группе станет 12 объектов, даже если по плану должно было быть больше.
this.group.createMultiple({ key: 'diamonds', frame: [0,1,2,3,4], repeat: 4, max: 12 });

Параметр max — это страховка. Он гарантирует, что вы не создадите объектов больше, чем нужно, что важно для управления производительностью, особенно на мобильных устройствах.

Практическое применение в игре

Где это может пригодиться?

1. **Создание поля звезд или монет:** Задайте один спрайт, randomFrame для легких вариаций цвета и большое frameQuantity. 2. **Инициализация пула снарядов:** Создайте группу снарядов (bullets) в начале игры с помощью createMultiple и используйте методы группы get и getFirstDead для их переиспользования. Это основа паттерна "объектный пул". 3. **Генерация фоновых элементов:** Для параллакс-фона можно быстро создать несколько слоев облаков или гор с разными кадрами.

Пример создания пула:

create() {
    this.bullets = this.add.group();
    // Создаем 30 снарядов "про запас", но скрываем их.
    this.bullets.createMultiple({
        key: 'bullet',
        repeat: 29,
        active: false,
        visible: false
    });
}

fire(x, y) {
    // Достаем из пула первый неактивный снаряд.
    const bullet = this.bullets.getFirstDead(false);
    if (bullet) {
        bullet.setActive(true).setVisible(true).setPosition(x, y);
        // ... настраиваем физику и т.д.
    }
}

Обратите внимание на параметры active: false и visible: false. Они позволяют создать объекты, которые изначально не обновляются и не отрисовываются, пока не понадобятся.

Что попробовать дальше

Метод Group.createMultiple — это мощный и гибкий инструмент для массового создания объектов в Phaser. Он избавляет от написания шаблонных циклов, делает код чище и позволяет легко экспериментировать с количеством и внешним видом объектов через понятные параметры. Для экспериментов попробуйте: 1. Скомбинировать randomFrame и yoyo — как Phaser будет обрабатывать эту команду? 2. Создать интерфейс уровня, где параметры frameQuantity, repeat и max задаются динамически, в зависимости от сложности. 3. Использовать createMultiple не только для спрайтов, но и для точечных светов (lights) или частиц (particles), если ваш тип игры это поддерживает.