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

При создании аркадных игр часто нужно ограничить перемещение объектов определённой областью экрана — например, рамкой уровня или видимой частью игрового мира. В Phaser с физикой Arcade это легко сделать, задав границы мира (world bounds). Эта статья покажет, как настроить такие границы и заставить объекты сталкиваться с ними, что полезно для создания лабиринтов, платформеров или игры в стиле «Арканоид».

Версия 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.image('cockpit', 'assets/pics/cockpit.png');
        this.load.spritesheet('ball', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
    }

    create ()
    {
        this.add.image(320, 200, 'bg');
        this.add.image(320, 200, 'cockpit').setScale(2);

        this.physics.world.setBounds(32, 20, 576, 240);

        const group = this.physics.add.group({
            key: 'ball',
            frameQuantity: 48,
            bounceX: 1,
            bounceY: 1,
            collideWorldBounds: true,
            velocityX: 200,
            velocityY: 150
        });

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

const config = {
    type: Phaser.AUTO,
    width: 640,
    height: 400,
    parent: 'phaser-example',
    pixelArt: true,
    physics: {
        default: 'arcade',
        arcade: {
            // You can also set the world bounds here:
            // x: 32, y: 20, width: 576, height: 240,
            gravity: { y: 200 }
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Что такое границы мира (World Bounds)?

В Arcade Physics мир — это виртуальное пространство, в котором происходят физические расчёты. По умолчанию оно совпадает с размером игрового холста (canvas). Однако вы можете изменить его, задав свои границы с помощью this.physics.world.setBounds(). Это позволяет создать область, за пределы которой объекты не смогут вылететь, если у них включено свойство collideWorldBounds.

В примере границы установлены внутри сцены, оставляя небольшой отступ от краёв экрана. Это создаёт эффект «иллюминатора», внутри которого движутся шары.

Настройка границ через код

Границы мира можно задать двумя способами: в конфигурации игры или динамически в сцене. В примере используется второй вариант — вызов метода setBounds() в функции create(). Это удобно, если границы нужно менять во время игры.

this.physics.world.setBounds(32, 20, 576, 240);

Параметры метода: `x,y— координаты левого верхнего угла области,widthиheight` — её размеры. Здесь границы смещены от краёв холста (640x400), создавая рамку.

Создание группы объектов с физикой

Чтобы продемонстрировать работу границ, в примере создаётся группа (Group) из спрайтов шаров с физикой. Группа позволяет управлять множеством объектов как единым целым.

const group = this.physics.add.group({
    key: 'ball',
    frameQuantity: 48,
    bounceX: 1,
    bounceY: 1,
    collideWorldBounds: true,
    velocityX: 200,
    velocityY: 150
});

Ключевые параметры: - key — текстура для спрайтов. - frameQuantity — количество создаваемых объектов. - bounceX, bounceY — упругость отскока (1 означает полное сохранение скорости). - collideWorldBounds: true — включает столкновение с границами мира. - velocityX, velocityY — начальная скорость по осям.

Распределение объектов по области

После создания группы шары нужно разместить в пределах границ мира. Для этого используется Phaser.Actions.RandomRectangle() — метод, который случайным образом распределяет массив объектов внутри заданного прямоугольника.

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

Первый аргумент — массив детей группы (получается через getChildren()), второй — прямоугольник границ мира (this.physics.world.bounds). Это удобная альтернатива ручному позиционированию каждого объекта.

Альтернатива: задание границ в конфиге

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

physics: {
    default: 'arcade',
    arcade: {
        x: 32,
        y: 20,
        width: 576,
        height: 240,
        gravity: { y: 200 }
    }
}

Параметры `x,y,width,heightвнутриarcadeавтоматически устанавливаютsetBounds()`. В примере этот способ закомментирован, но он полностью эквивалентен вызову из кода сцены.

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

Установка границ мира — простой способ контролировать перемещение физических объектов в Phaser. Это основа для многих игровых механик: от отскакивающих шаров до ограничения камеры в платформерах. Попробуйте экспериментировать: изменяйте размер границ во время игры, создавайте «порталы» для выхода за пределы области или комбинируйте collideWorldBounds с другими телами для сложных взаимодействий.