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

Физический движок Arcade в 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('block', 'assets/sprites/block.png');
    }

    create ()
    {
        const group = this.physics.add.group({
            defaultKey: 'block',
            bounceX: 1,
            bounceY: 1,
            collideWorldBounds: true
        });

        // World gravity
        this.physics.world.gravity.y = 150;

        // Total gravity is 150.
        group.create(250, 300);

        // Total gravity is 450.
        group.create(350, 300).setGravity(0, 300);

        // Total gravity is 150.
        group.create(450, 300).setGravity(0, -300);

        // No gravity.
        group.create(550, 300, 'block').body.setAllowGravity(false);
    }
}

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

const game = new Phaser.Game(config);

Настройка мировой гравитации

В Arcade Physics гравитация может быть задана для всего физического мира. Это базовый уровень, влияющий на все тела, у которых не отключена гравитация явно. Гравитация задается через свойство gravity объекта this.physics.world.

// Устанавливаем вертикальную гравитацию для всего мира.
// Положительное значение тянет объекты вниз.
this.physics.world.gravity.y = 150;

После этой настройки все физические тела в сцене будут подвержены силе тяжести, тянущей их вниз со скоростью 150 пикселей в секунду в квадрате (px/s²). Это значение можно менять динамически во время выполнения игры.

Создание физической группы

Для удобной работы с множеством однотипных объектов используется физическая группа (Physics Group). Она позволяет задать общие свойства для всех создаваемых в ней тел.

const group = this.physics.add.group({
    defaultKey: 'block', // Текстура по умолчанию
    bounceX: 1,          // Идеальный отскок по оси X (без потерь энергии)
    bounceY: 1,          // Идеальный отскок по оси Y
    collideWorldBounds: true // Столкновение с границами мира
});

Группа создается с помощью метода this.physics.add.group(). Параметр defaultKey указывает ключ текстуры, которая будет автоматически использоваться для новых спрайтов в группе. Свойства bounceX и bounceY определяют упругость объектов, а collideWorldBounds включает столкновение с краями игрового поля.

Индивидуальная гравитация для тел

Сила гравитации для отдельного тела задается методом setGravity(). Эта гравитация добавляется к мировой. Если мировая гравитация равна 150, а для тела установлена своя гравитация 300, то общая сила, действующая на тело, составит 450.

// Создаем спрайт в группе. На него действует только мировая гравитация (150).
group.create(250, 300);

// Создаем спрайт и задаем ему дополнительную гравитацию.
// Общая гравитация: мировая (150) + индивидуальная (300) = 450.
group.create(350, 300).setGravity(0, 300);

// Можно задать отрицательное значение, чтобы тянуть объект вверх.
// Общая гравитация: 150 + (-300) = -150 (объект летит вверх).
group.create(450, 300).setGravity(0, -300);

Метод setGravity() принимает два аргумента: гравитацию по оси X и по оси Y. В нашем примере изменяется только вертикальная составляющая.

Полное отключение гравитации

Иногда объект не должен подвергаться воздействию гравитации. Например, это может быть платформа, парящая в воздухе, или объект, управляемый игроком. Для этого у физического тела (body) нужно установить свойство allowGravity в false.

// Создаем спрайт и получаем доступ к его физическому телу.
// Метод setAllowGravity(false) полностью отключает гравитацию для этого тела.
group.create(550, 300, 'block').body.setAllowGravity(false);

Обратите внимание: чтобы отключить гравитацию, нужно обратиться к свойству .body созданного спрайта. Метод setAllowGravity(false) гарантирует, что ни мировая, ни индивидуальная гравитация на этот объект действовать не будут.

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

Гравитация в Phaser Arcade Physics — это многоуровневая система. Вы можете задать общие правила для всей сцены через this.physics.world.gravity, а затем тонко настраивать поведение отдельных объектов с помощью setGravity() или полностью отключать его через setAllowGravity(). Для экспериментов попробуйте: 1. Динамически менять мировую гравитацию по таймеру или событию. 2. Создать область с "аномальной" гравитацией, где объекты притягиваются в сторону. 3. Реализовать прыжок персонажа, временно отключая для него гравитацию и задавая вертикальную скорость.