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

Использование прямоугольных и круглых коллайдеров подходит для многих игр, но иногда объектам нужна более точная физическая форма. Встроенный в 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: 'trapezoid',
            width: 128,
            height: 64,
            slope: 0.6
        });

        //  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

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

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#1b1464',
    parent: 'phaser-example',
    physics: {
        default: 'matter', // Активация движка Matter.js
        matter: {
            debug: true // Визуализация hitbox'ов
        }
    },
    scene: Example
};

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

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

Для создания физического объекта используется фабричный метод this.matter.add.image(). Он создает и возвращает объект MatterImage, который сочетает в себе спрайт и связанное с ним твердое тело (Body) из движка Matter.js.

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

На этом этапе объект poly имеет стандартное прямоугольное тело, совпадающее по размеру с загруженной текстурой 'orange'. Чтобы изменить форму, нам потребуется отдельный вызов.

Определение трапециевидной формы

Ключевой метод setBody() заменяет стандартное тело объекта на новое, с заданной геометрией. Для создания трапеции в качестве type указывается 'trapezoid'.

poly.setBody({
    type: 'trapezoid',
    width: 128,   // Ширина основания трапеции
    height: 64,   // Высота трапеции
    slope: 0.6    // Коэффициент наклона боковых сторон
});

Параметр slope определяет, насколько боковые стороны скошены внутрь. Значение 0 создаст прямоугольник, а значение 1 — треугольник (верхняя сторона будет нулевой длины). Значение 0.6 дает нам ярко выраженную трапецию. Matter.js сам рассчитывает вершины полигона на основе этих параметров.

Настройка динамики движения

После определения формы мы задаем телу начальное движение и физические свойства. Это делается с помощью методов самого объекта MatterImage.

//  Задаем начальную линейную скорость по осям X и Y
poly.setVelocity(6, 3);

//  Задаем начальную скорость вращения
poly.setAngularVelocity(0.01);

//  Устанавливаем коэффициент упругости (1 - абсолютно упругий удар)
poly.setBounce(1);

//  Отключаем трение: статическое, динамическое, воздушное
poly.setFriction(0, 0, 0);

Комбинация setBounce(1) и setFriction(0, 0, 0) заставляет тело бесконечно отскакивать от границ мира без потерь энергии, создавая эффект идеального бильярдного шара, но трапециевидной формы. Ненулевая angularVelocity заставляет его медленно вращаться в полете.

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

Создание кастомных полигональных тел в Matter.js — мощный инструмент для повышения реалистичности и вариативности игровой физики. Трапеция — лишь один пример из множества возможных форм (полигон, круг, прямоугольник). Для экспериментов попробуйте изменить параметр slope на 0.2 или 0.9, чтобы увидеть, как меняется геометрия. Используйте другие типы тел (type: 'polygon'), задавая вершины вручную. Или примените этот подход к группе объектов, создав сложную механическую конструкцию из нетривиальных деталей.