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

Реалистичное движение объектов — ключ к увлекательному геймплею. Встроенный в Phaser Arcade Physics предлагает мощные инструменты для симуляции сопротивления среды и инерции. В этой статье мы разберем, как использовать свойства `setDamping` и `setDrag` для создания движения, которое плавно замедляется и останавливается, что идеально подходит для симуляции скольжения по льду, движения в воде или просто для придания веса вашим спрайтам. Вы научитесь контролировать, как быстро объект теряет скорость, и даже предсказывать время его остановки.

Версия 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 ()
    {
        this.physics.add.image(100, 100, 'block').setVelocityX(100).setDamping(true).setDrag(0.5);
        this.physics.add.image(100, 200, 'block').setVelocityX(100).setDamping(true).setDrag(0.2);
        this.physics.add.image(100, 300, 'block').setVelocityX(100).setDamping(true).setDrag(0.1);
        this.physics.add.image(100, 400, 'block').setVelocityX(100).setDamping(true).setDrag(0.05);
        this.physics.add.image(100, 500, 'block').setVelocityX(100).setDamping(true).setDrag(0.01);

        const bodies = Array.from(this.physics.world.bodies);
        for (const body of bodies)
        {
            const { drag, velocity } = body;

            console.log('Body will stop after %.3f seconds', Math.log(0.001 / velocity.x) / Math.log(drag.x));
        }
    }

    update ()
    {
        const bodies = Array.from(this.physics.world.bodies);
        for (const body of bodies)
        {
            body.debugBodyColor = body.speed > 0 ? 0x00ff00 : 0xff0000;
        }
    }
}

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);

Настройка сцены и физики

Перед началом работы с физическими телами необходимо настроить саму сцену и движок физики. В Phaser это делается в конфигурационном объекте игры. Мы указываем, что по умолчанию используется система Arcade Physics и включаем отладочный режим для визуализации коллайдеров.

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);

В методе preload загружается единственный спрайт — изображение блока, которое будет использоваться для всех физических тел в этом примере. Базовый URL упрощает загрузку ассетов из репозитория с примерами.

Создание тел с сопротивлением (Drag)

В методе create создается пять идентичных физических тел-изображений, расположенных вертикально. Каждому из них сразу задается начальная горизонтальная скорость в 100 пикселей в секунду с помощью setVelocityX(100). Ключевое отличие между ними — значение коэффициента сопротивления (Drag), устанавливаемого методом setDrag().

create ()
{
    this.physics.add.image(100, 100, 'block').setVelocityX(100).setDamping(true).setDrag(0.5);
    this.physics.add.image(100, 200, 'block').setVelocityX(100).setDamping(true).setDrag(0.2);
    this.physics.add.image(100, 300, 'block').setVelocityX(100).setDamping(true).setDrag(0.1);
    this.physics.add.image(100, 400, 'block').setVelocityX(100).setDamping(true).setDrag(0.05);
    this.physics.add.image(100, 500, 'block').setVelocityX(100).setDamping(true).setDrag(0.01);
    // ...
}

Метод setDamping(true) включает режим демпфирования. В этом режиме свойство drag работает как множитель скорости в каждом кадре, а не как постоянная сила. Значение drag должно быть между 0 и 1. Чем оно ближе к 1, тем быстрее объект остановится (например, 0.5 — быстрое замедление). Чем ближе к 0, тем дольше объект будет сохранять инерцию (0.01 — очень плавное и долгое скольжение).

Прогнозирование времени остановки

Одно из преимуществ использования damping — возможность аналитически рассчитать время, через которое тело остановится, при известной начальной скорости и коэффициенте drag. В примере это демонстрируется сразу после создания тел. Код проходит по всем телам в физическом мире и вычисляет время до остановки, используя логарифмическую формулу.

const bodies = Array.from(this.physics.world.bodies);
for (const body of bodies)
{
    const { drag, velocity } = body;
    console.log('Body will stop after %.3f seconds', Math.log(0.001 / velocity.x) / Math.log(drag.x));
}

Формула Math.log(0.001 / velocity.x) / Math.log(drag.x) выводит время в секундах. Константа 0.001 — это пороговая скорость, ниже которой тело считается остановившимся (поскольку скорость теоретически никогда не достигнет абсолютного нуля при таком расчете). Это мощный инструмент для геймдизайна, позволяющий точно настраивать длительность анимаций или событий, связанных с движением.

Визуальная отладка в реальном времени

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

update ()
{
    const bodies = Array.from(this.physics.world.bodies);
    for (const body of bodies)
    {
        body.debugBodyColor = body.speed > 0 ? 0x00ff00 : 0xff0000;
    }
}

Здесь body.speed — это текущая общая скорость тела (скаляр). Пока скорость больше нуля, цвет обводки устанавливается зеленым (0x00ff00). Как только тело (почти) останавливается, цвет становится красным (0xff0000). Такой прием крайне полезен при тонкой настройке физических параметров, позволяя сразу видеть результат.

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

Свойства setDamping и setDrag в Arcade Physics — это простой, но эффективный способ добавить реалистичную инерцию в вашу игру. Вы можете использовать их для создания разнообразных поверхностей: от липкой грязи (высокий drag) до идеального льда (очень низкий drag). Для экспериментов попробуйте

  1. Привязать коэффициент drag к свойству спрайта (например, «весу» персонажа)
  2. Динамически менять drag при столкновении с определенными объектами (например, выход из воды на сушу)
  3. Комбинировать damping с другими силами, например, с ускорением, чтобы создать ощущение движения на реактивной тяге с последующим выбегом