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

Создание игровых сцен часто требует размещения десятков или сотен объектов в определенной области. Делать это вручную — долго и неэффективно. В этой статье мы разберем, как с помощью одного вызова `Phaser.Actions.RandomEllipse` можно мгновенно распределить множество спрайтов внутри эллипса, создав интересные визуальные эффекты или скопления объектов, например, стаю птиц или россыпь звёзд. Этот метод не только экономит время, но и добавляет вашей сцене элемент естественной, управляемой случайности.

Версия 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('orb', 'assets/sprites/orb-blue.png');
    }

    create ()
    {
        //  Create 300 sprites (they all start life at 0x0)
        const group = this.add.group({ key: 'orb', frameQuantity: 300 });

        this.ellipse = new Phaser.Geom.Ellipse(400, 300, 100, 200);

        //  Randomly position the sprites within the ellipse
        Phaser.Actions.RandomEllipse(group.getChildren(), this.ellipse);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Подготовка сцены и создание группы спрайтов

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

В методе preload загружается одно изображение. Затем, в create, с помощью конфигурационного объекта создается группа из 300 спрайтов. Все они изначально имеют координаты (0, 0). Ключевой параметр frameQuantity указывает, сколько копий спрайта 'orb' нужно создать.

const group = this.add.group({ key: 'orb', frameQuantity: 300 });

Определение области размещения: геометрия эллипса

Чтобы случайным образом распределить спрайты, нужно задать границы области. В Phaser для этого есть объекты геометрии. Мы создаем экземпляр Phaser.Geom.Ellipse.

Конструктор принимает четыре аргумента: координаты центра по осям X и Y, а затем ширину и высоту эллипса. В нашем примере эллипс расположен в центре экрана (400, 300) и имеет ширину 100 и высоту 200 пикселей. Этот объект будет использоваться как маска для размещения.

this.ellipse = new Phaser.Geom.Ellipse(400, 300, 100, 200);

Массовое распределение объектов: Phaser.Actions.RandomEllipse

Самый важный этап — применение действия (Action) к массиву объектов. Phaser.Actions.RandomEllipse — это статический метод, который принимает массив игровых объектов (в нашем случае — детей группы) и объект Ellipse. Он перебирает все объекты в массиве и задает каждой случайную позицию (x, y) внутри заданного эллипса.

Метод group.getChildren() возвращает массив всех спрайтов, созданных в группе. После вызова действия все 300 сфер мгновенно "разбросаны" внутри эллиптической области.

Phaser.Actions.RandomEllipse(group.getChildren(), this.ellipse);

Сборка всего вместе: конфигурация игры

Для запуска примера необходима стандартная конфигурация игры Phaser. В ней указывается тип рендерера, размеры холста, цвет фона, ID родительского HTML-элемента и класс нашей сцены Example. Создание экземпляра Phaser.Game с этой конфигурацией инициирует выполнение всех описанных методов: preload, create и далее игрового цикла.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

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

Использование Phaser.Actions.RandomEllipse — это мощный и лаконичный способ наполнить сцену объектами по заданной форме. Для экспериментов попробуйте изменить параметры эллипса (сделать его кругом или очень вытянутым), анимировать сам эллипс, перемещая его центр, и затем повторно применять действие для создания динамических скоплений. Также можно комбинировать это действие с другими, например, RandomCircle или PlaceOnCircle, для создания более сложных паттернов расстановки.