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

Создание динамичной сцены с множеством объектов, которые случайным образом разлетаются в разные стороны — частая задача в аркадных играх. Этот пример демонстрирует, как эффективно использовать группы физических тел (`Physics 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.image('bg', 'assets/skies/space2.png');
        this.load.spritesheet('ball', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
    }

    create ()
    {
        this.add.image(400, 300, 'bg');

        const balls = this.physics.add.group({
            key: 'ball',
            frame: [ 0, 1, 2, 3 ],
            quantity: 12,
            bounceX: 1,
            bounceY: 1,
            collideWorldBounds: true
        });

        Phaser.Actions.RandomRectangle(balls.getChildren(), this.physics.world.bounds);

        for (const ball of balls.getChildren())
        {
            Phaser.Math.RandomXY(ball.body.velocity, 100);
        }
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    physics: {
        default: 'arcade',
        arcade: {
            debug: false
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Инициализация группы физических объектов

Вместо создания и настройки каждого спрайта по отдельности, Phaser позволяет работать с группами. Группа физических тел (Physics Group) создается с предустановленными физическими свойствами для всех своих членов.

const balls = this.physics.add.group({
    key: 'ball',
    frame: [ 0, 1, 2, 3 ],
    quantity: 12,
    bounceX: 1,
    bounceY: 1,
    collideWorldBounds: true
});

Ключевые параметры: * key: Ключ загруженного спрайтшита. * frame: Массив индексов кадров из спрайтшита. Каждый новый объект в группе будет использовать следующий кадр из этого массива, что позволяет легко создать визуальное разнообразие. * quantity: Количество создаваемых объектов. * bounceX, bounceY: Коэффициент упругости (1 — идеальный отскок). * collideWorldBounds: Включение столкновений с границами мира — объекты не будут вылетать за пределы сцены.

Случайное размещение объектов в пределах области

После создания группы все объекты находятся в одной точке. Метод Phaser.Actions.RandomRectangle позволяет мгновенно распределить их по случайным координатам внутри заданного прямоугольника.

Phaser.Actions.RandomRectangle(balls.getChildren(), this.physics.world.bounds);

* balls.getChildren() возвращает массив всех дочерних спрайтов в группе. * this.physics.world.bounds — это прямоугольник, совпадающий с границами физического мира (в нашем случае 800x600 пикселей). Все 12 шаров будут равномерно распределены внутри этой области.

Назначение случайных векторов скорости

Чтобы объекты начали двигаться, каждому нужно задать скорость (velocity). Утилита Phaser.Math.RandomXY вычисляет случайный вектор с заданной максимальной длиной и записывает его в свойство velocity физического тела объекта.

for (const ball of balls.getChildren())
{
    Phaser.Math.RandomXY(ball.body.velocity, 100);
}

* ball.body.velocity — свойство тела Arcade Physics, отвечающее за скорость по осям X и Y. * Второй аргумент 100 определяет максимальную скорость (в пикселях в секунду). Фактическая скорость каждого шара будет случайным вектором с длиной от 0 до 100. Благодаря свойствам bounce и collideWorldBounds, шары будут хаотично и бесконечно отскакивать от границ экрана и друг от друга.

Настройка сцены и физики

Важно правильно сконфигурировать игру, чтобы задействовать Arcade Physics систему.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    physics: {
        default: 'arcade', // Подключаем движок Arcade Physics
        arcade: {
            debug: false // Отключаем отладочную визуализацию
        }
    },
    scene: Example
};

Без указания physics.default: 'arcade' вызовы методов this.physics.add.group и доступ к ball.body были бы невозможны.

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

Использование Physics Group в сочетании с утилитами Actions и Math — мощный и производительный подход для создания динамичных сцен с множеством объектов. Этот паттерн легко адаптировать под различные игровые механики. **Идеи для экспериментов:** 1. Измените параметры bounce на значение меньше 1, чтобы шары теряли энергию при отскоке. 2. Вместо случайного распределения скорости внутри цикла, задайте разную максимальную скорость для разных типов шаров (кадров). 3. Добавьте обработку столкновений между шарами, используя this.physics.add.collider(balls, balls), чтобы они сталкивались и отталкивались друг от друга.