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

В игровой физике не все объекты должны подчиняться одним законам. Например, платформерам нужны летающие платформы, а в космических симуляторах — астероиды, не падающие на планеты. В этом примере показано, как в 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('block', 'assets/sprites/block.png');
        this.load.image('platform', 'assets/sprites/platform.png');
    }

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

        //  This body isn't effected by Gravity
        this.matter.add.image(100, 100, 'block').setIgnoreGravity(true);

        this.matter.add.image(300, 100, 'block', null, { restitution: 0.6, frictionAir: 0, mass: 0.1 });
        this.matter.add.image(500, 100, 'block', null, { restitution: 0.8, frictionAir: 0, mass: 0.1 });
        this.matter.add.image(700, 100, 'block', null, { restitution: 1, frictionAir: 0, mass: 0.1 });
    }
}

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

const game = new Phaser.Game(config);

Настройка физики Matter.js

Первым делом в конфигурации игры нужно активировать физический движок Matter.js. Это делается в объекте config, который передаётся конструктору Phaser.Game.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#1b1464',
    parent: 'phaser-example',
    physics: {
        default: 'matter' // Активируем Matter.js как движок по умолчанию
    },
    scene: Example
};

Ключевой параметр — physics.default: 'matter'. Без него методы this.matter в сцене будут недоступны. Также важно, что в Matter.js для работы мировых границ (стен) нужно явно их создавать, в отличие от Arcade Physics.

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

В методе create() сцены инициализируется физический мир. Вызов this.matter.world.setBounds() создаёт непроходимые границы по краям игрового поля.

create ()
{
    this.matter.world.setBounds();
    // ... создание объектов
}

Метод setBounds() без аргументов использует размеры игрового мира, определённые в config. Это стандартный способ оградить игровое пространство. Внутри этих границ и будут взаимодействовать все физические тела.

Создание тела, игнорирующего гравитацию

В Matter.js каждое тело можно наделить уникальными свойствами. В примере первое тело создаётся так, чтобы на него не действовала сила тяжести.

this.matter.add.image(100, 100, 'block').setIgnoreGravity(true);

Метод this.matter.add.image() создаёт физическое тело на основе спрайта. Цепочка вызовов .setIgnoreGravity(true) применяется к только что созданному телу и устанавливает его свойство ignoreGravity в true. Это значит, что глобальная гравитация мира (по умолчанию направленная вниз) на это тело действовать не будет. Оно останется висеть в воздухе на той позиции, где было создано.

Сравнение с обычными физическими телами

Чтобы продемонстрировать разницу, в примере создаются ещё три блока, которые гравитации подчиняются. Они будут падать и отскакивать от нижней границы.

this.matter.add.image(300, 100, 'block', null, { restitution: 0.6, frictionAir: 0, mass: 0.1 });
this.matter.add.image(500, 100, 'block', null, { restitution: 0.8, frictionAir: 0, mass: 0.1 });
this.matter.add.image(700, 100, 'block', null, { restitution: 1, frictionAir: 0, mass: 0.1 });

Эти блоки создаются с дополнительными физическими параметрами, переданными пятым аргументом: * restitution — упругость (от 0 до 1). Блок с restitution: 1 отскочит от земли почти без потерь энергии. * frictionAir: 0 — отсутствие сопротивления воздуха, чтобы падение и отскоки были идеальными. * mass: 0.1 — малая масса для более динамичного движения. При запуске примера эти три блока упадут, а первый блок, созданный с setIgnoreGravity(true), останется на месте.

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

Метод setIgnoreGravity() — это мощный инструмент для тонкой настройки физики. Он позволяет нарушать общие правила для отдельных объектов, что открывает простор для дизайна уровней. Попробуйте поэкспериментировать: создайте платформу, которая парит в воздухе, или снаряд, летящий по прямой в невесомости. Можно комбинировать это свойство с другими, например, сделать тело не только невесомым, но и статичным (setStatic(true)), чтобы создать абсолютно неподвижную опору в воздухе.