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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    group;
    sprite;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('mushroom', 'assets/sprites/mushroom2.png');
        this.load.image('ball', 'assets/sprites/shinyball.png');
    }

    create ()
    {
        this.sprite = this.physics.add.image(400, 300, 'mushroom');

        this.group = this.physics.add.group({
            key: 'ball',
            frameQuantity: 30,
            immovable: true
        });

        Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), new Phaser.Geom.Rectangle(84, 84, 616, 416));

        this.sprite.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true).setGravityY(200);
    }

    update ()
    {
        this.physics.world.collide(this.sprite, this.group);
    }
}

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

const game = new Phaser.Game(config);

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

В классе Example, который расширяет Phaser.Scene, определены два свойства: group для хранения группы объектов и sprite для одиночного спрайта.

В методе preload загружаются два изображения, которые будут использоваться в качестве спрайтов. Базовый URL задаётся для удобства доступа к ресурсам из репозитория с примерами.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('mushroom', 'assets/sprites/mushroom2.png');
    this.load.image('ball', 'assets/sprites/shinyball.png');
}

Создание физических объектов

Метод create инициализирует физический мир. Сначала создаётся динамический спрайт с физическим телом, используя this.physics.add.image. Этот спрайт будет двигаться и сталкиваться с другими объектами.

this.sprite = this.physics.add.image(400, 300, 'mushroom');

Затем создаётся группа физических объектов (this.physics.add.group). Ключевые параметры: - key: текстура для всех спрайтов в группе. - frameQuantity: количество создаваемых спрайтов (30). - immovable: true: делает все тела в группе неподвижными при столкновениях, что критически важно для корректной физики.

this.group = this.physics.add.group({
    key: 'ball',
    frameQuantity: 30,
    immovable: true
});

Расположение объектов и настройка физики

После создания группы её элементы нужно разместить на сцене. Используется Phaser.Actions.PlaceOnRectangle, которая распределяет все дочерние спрайты группы по периметру заданного прямоугольника.

Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), new Phaser.Geom.Rectangle(84, 84, 616, 416));

Далее для одиночного спрайта настраиваются физические свойства через цепочку методов: - setVelocity(100, 200): задаёт начальную скорость по осям X и Y. - setBounce(1, 1): устанавливает коэффициент упругости (1 означает идеальный отскок). - setCollideWorldBounds(true): включает столкновения с границами мира. - setGravityY(200): применяет вертикальную гравитацию к спрайту.

this.sprite.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true).setGravityY(200);

Обработка столкновений в реальном времени

В методе update, который вызывается на каждом кадре, происходит проверка и обработка столкновений между спрайтом и группой объектов. Для этого используется this.physics.world.collide.

this.physics.world.collide(this.sprite, this.group);

Система Arcade Physics автоматически вычисляет пересечения тел и применяет физические реакции (отскок, остановку), основываясь на их свойствах, таких как immovable и bounce. Это позволяет реализовать сложное взаимодействие с минимальным кодом.

Конфигурация игры и запуск

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

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

Ключевой параметр debug: true включает отладочную визуализацию физических тел, что помогает при разработке. Игра создаётся инстанцированием Phaser.Game с этой конфигурацией.

const game = new Phaser.Game(config);

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

Пример наглядно показывает, как Phaser Arcade Physics упрощает реализацию столкновений между одиночными объектами и группами. Для экспериментов попробуйте: изменить параметры velocity, bounce или gravity у спрайта; сделать группу подвижной, убрав immovable; добавить обработчики событий столкновения через collideCallback; или использовать другие формы размещения объектов, например, PlaceOnCircle.