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

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

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

    create ()
    {
        const image1 = this.add.image(0, -30, 'mushroom');
        const image2 = this.add.image(-40, 30, 'mushroom');
        const image3 = this.add.image(40, 30, 'mushroom');

        const container = this.add.container(100, 100, [ image1, image2, image3 ]);

        //  A Container has a default size of 0x0, so we need to give it a size before enabling a physics body
        container.setSize(128, 64);

        const physicsContainer = this.matter.add.gameObject(container);

        physicsContainer.setFrictionAir(0.001);
        physicsContainer.setBounce(0.9);

        this.matter.add.image(350, 450, 'platform', null, { isStatic: true }).setScale(2, 0.5).setAngle(10);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#1b1464',
    parent: 'phaser-example',
    physics: {
        default: 'matter',
        matter: {
            debug: true,
            gravity: {
                y: 0.3
            }
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

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

Класс сцены наследуется от Phaser.Scene. В методе preload задаётся базовый URL для загрузки ресурсов и загружаются два изображения: спрайт гриба и платформы.

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

Создание контейнера и его содержимого

В методе create создаются три отдельных изображения гриба. Координаты (0, -30), (-40, 30) и (40, 30) задаются относительно будущей позиции контейнера. Затем эти изображения добавляются в контейнер.

const image1 = this.add.image(0, -30, 'mushroom');
const image2 = this.add.image(-40, 30, 'mushroom');
const image3 = this.add.image(40, 30, 'mushroom');

const container = this.add.container(100, 100, [ image1, image2, image3 ]);

Контейнер изначально имеет нулевой размер, что непригодно для физики. Поэтому перед созданием тела необходимо явно задать его размеры с помощью метода setSize. В данном случае задаётся прямоугольная область 128x64 пикселя, которая будет коллайдером для физического тела.

container.setSize(128, 64);

Добавление физики Matter к контейнеру

Ключевой шаг — превращение обычного контейнера в физический объект системы Matter. Это делает метод this.matter.add.gameObject(). Он принимает игровой объект (в нашем случае контейнер) и добавляет к нему компоненты физического тела.

const physicsContainer = this.matter.add.gameObject(container);

После этого к объекту physicsContainer можно применять методы физики Matter, такие как setFrictionAir для задания сопротивления воздуха и setBounce для коэффициента отскока.

physicsContainer.setFrictionAir(0.001);
physicsContainer.setBounce(0.9);

Создание статической платформы

Чтобы составной объект мог с чем-то взаимодействовать, создаётся статическая платформа. Она не будет двигаться под действием сил. Метод this.matter.add.image создаёт изображение с физическим телом Matter. Параметр { isStatic: true } делает тело статическим. После создания платформа масштабируется и поворачивается.

this.matter.add.image(350, 450, 'platform', null, { isStatic: true }).setScale(2, 0.5).setAngle(10);

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

Конфигурационный объект игры включает настройки физического движка Matter. Важно установить default: 'matter' в разделе physics. В подразделе matter включается отладка (debug: true), чтобы видеть контуры тел, и задаётся слабая гравитация по оси Y.

physics: {
    default: 'matter',
    matter: {
        debug: true,
        gravity: {
            y: 0.3
        }
    }
}

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

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