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

При создании игр с физикой форма коллайдера объекта — краеугольный камень реалистичного поведения. Часто спрайт имеет сложную форму, которую прямоугольный или круглый хитбокс описывает плохо. Phaser в связке с движком Matter.js позволяет легко создавать полигональные (многоугольные) тела, не зависящие от текстуры спрайта. Это открывает путь к точным и визуально приятным столкновениям для объектов любой формы — от шестиугольных гаек до неправильных астероидов.

Версия 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('orange', 'assets/sprites/columns-orange.png');
    }

    create ()
    {
        this.matter.world.setBounds().disableGravity();

        const poly = this.matter.add.image(200, 50, 'orange');

        poly.setBody({
            type: 'polygon',
            sides: 6,
            radius: 64
        });

        //  Just make the body move around and bounce
        poly.setVelocity(6, 3);
        poly.setAngularVelocity(0.01);
        poly.setBounce(1);
        poly.setFriction(0, 0, 0);
    }
}

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

const game = new Phaser.Game(config);

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

Вся работа начинается с корректной настройки физического движка Matter.js в конфигурации игры. Ключевой параметр debug: true включает отладочную отрисовку, которая будет визуализировать создаваемые нами полигональные тела.

const config = {
    type: Phaser.AUTO,
    physics: {
        default: 'matter',
        matter: {
            debug: true // Включаем отладочную отрисовку тел
        }
    },
    scene: Example
};

В методе create() сцены мы подготавливаем мир. Вызов setBounds() автоматически создает статические стены по границам мира, а disableGravity() отключает гравитацию, чтобы наше тело двигалось по заданной нами траектории.

create ()
{
    this.matter.world.setBounds().disableGravity();
    // ... Дальнейший код создания тела
}

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

Изначально физическое тело создается на основе прямоугольного контура (баундинг бокса) изображения. Мы создаем физический спрайт с помощью this.matter.add.image. На этом этапе тело спрайта — это прямоугольник размером с текстуру 'orange'.

const poly = this.matter.add.image(200, 50, 'orange');

Важно понимать, что теперь poly — это не просто изображение, а комплексный объект, содержащий и спрайт для отрисовки, и физическое тело (body) для расчетов столкновений и движения.

Переопределение формы тела на полигональную

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

poly.setBody({
    type: 'polygon', // Указываем тип тела — многоугольник
    sides: 6,        // Количество сторон
    radius: 64       // Радиус описанной окружности
});

После этого вызова физическое тело poly становится правильным шестиугольником с радиусом 64 пикселя. Обратите внимание: спрайт с изображением апельсиновой колонны продолжает отрисовываться, но столкновения теперь рассчитываются по невидимому шестиугольнику, который мы видим благодаря включенному дебаг-режиму (зеленый контур). Это мощный прием для создания точной физики у объектов со сложными визуальными формами.

Задание движения и физических свойств

Когда тело создано, мы можем управлять его динамикой. В примере задается начальная скорость, вращение, упругость и трение. Эти свойства применяются уже к новому полигональному телу.

//  Задаем линейную скорость по осям X и Y
poly.setVelocity(6, 3);
//  Задаем угловую скорость (вращение)
poly.setAngularVelocity(0.01);
//  Устанавливаем коэффициент упругости (1 = идеальный отскок)
poly.setBounce(1);
//  Отключаем трение: первое число — линейное, остальные — угловое и воздушное
poly.setFriction(0, 0, 0);

Благодаря setBounce(1) и отключенному трению тело будет бесконечно двигаться и отскакивать от границ мира (setBounds) без потери энергии, демонстрируя идеальную физику.

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

Метод setBody() в Matter.js — это ключ к созданию точной и производительной физики для объектов сложной формы. Вы больше не привязаны к прямоугольнику текстуры. Для экспериментов попробуйте: изменить число sides на 3 (треугольник) или 8 (восьмиугольник); использовать type: 'circle' или type: 'trapezoid'; привязать полигональное тело к анимированному спрайту; создать составное тело из нескольких простых фигур с помощью type: 'compound'.