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

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

Версия 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('block', 'assets/sprites/block.png');
        this.load.image('ball', 'assets/sprites/shinyball.png');
    }

    create ()
    {
        const blocks = this.physics.add.group({
            key: 'block',
            frameQuantity: 5,
            setXY: { x: 200, y: 100, stepY: 100 },
            bounceX: 1
        });

        const balls = this.physics.add.group({
            defaultKey: 'ball',
            bounceX: 1,
            velocityX: 100
        });

        balls.create(0, 100).setMass(0.1);
        balls.create(0, 200).setMass(0.5);
        balls.create(0, 300).setMass(1);
        balls.create(0, 400).setMass(5);
        balls.create(0, 500).setMass(10);

        for (const ball of balls.getChildren())
        {
            ball.setScale(ball.body.mass ** 0.333);
        }

        this.physics.add.collider(balls, blocks);
    }
}

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, мы начинаем с класса сцены, расширяющего Phaser.Scene. В методе preload() мы загружаем два спрайта: блок и шар. Обратите внимание на использование setBaseURL для указания базового пути к ресурсам.

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

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

В методе create() мы создаем две физические группы с помощью this.physics.add.group. Это удобный способ работать с множеством однотипных тел.

Группа blocks создает пять статических блоков, выстроенных вертикально. Параметр bounceX: 1 задает полное отскакивание по оси X.

const blocks = this.physics.add.group({
    key: 'block',
    frameQuantity: 5,
    setXY: { x: 200, y: 100, stepY: 100 },
    bounceX: 1
});

Группа balls будет содержать наши динамические шары. Мы задаем для нее defaultKey (основной спрайт) и начальные свойства: bounceX: 1 и velocityX: 100 (стартовая скорость по оси X).

const balls = this.physics.add.group({
    defaultKey: 'ball',
    bounceX: 1,
    velocityX: 100
});

Назначение массы и визуальная корреляция

Здесь происходит самое интересное. Мы создаем пять шаров на разных высотах и каждому назначаем уникальную массу через метод setMass(). Значения массы: 0.1, 0.5, 1, 5 и 10.

balls.create(0, 100).setMass(0.1);
balls.create(0, 200).setMass(0.5);
balls.create(0, 300).setMass(1);
balls.create(0, 400).setMass(5);
balls.create(0, 500).setMass(10);

Чтобы игрок мог наглядно видеть разницу в массе, мы изменяем масштаб каждого шара. Размер вычисляется как кубический корень из массы (mass ** 0.333), что примерно соответствует изменению объема. Таким образом, более массивный шар будет выглядеть крупнее.

for (const ball of balls.getChildren())
{
    ball.setScale(ball.body.mass ** 0.333);
}

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

Физическое взаимодействие между группами шаров и блоков настраивается одной строкой с помощью this.physics.add.collider. Движок Arcade Physics автоматически учтет массу объектов при расчете столкновений: более тяжелые шары будут сильнее воздействовать на блоки.

this.physics.add.collider(balls, blocks);

Конфигурация игры

Здесь определяется базовая конфигурация игры Phaser. Ключевой момент — включение физического движка arcade и его настройка.

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);

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

Использование массы в Arcade Physics — простой, но мощный способ добавить разнообразия в игровую механику. Вы можете экспериментировать: создавайте объекты с отрицательной массой для антигравитационных эффектов, комбинируйте массу с другими параметрами тела (например, drag или bounce), или используйте массу для расчета урона от столкновения. Попробуйте изменить в примере начальную скорость шаров или упругость блоков и понаблюдайте за изменениями в симуляции.