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

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

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

    create ()
    {
        const sprite1 = this.physics.add.image(100, 100, 'mushroom');
        const sprite2 = this.physics.add.image(400, 100, 'mushroom');

        sprite1.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);
        sprite2.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);

        this.physics.add.collider(sprite1, sprite2);
    }
}

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

const game = new Phaser.Game(config);


Настройка физики в конфигурации игры

Прежде чем добавлять физические объекты, необходимо активировать и настроить физический движок в конфигурации игры. Это делается в объекте config, который передается конструктору Phaser.Game. Ключевой параметр — physics.default, который указывает на используемый движок (в нашем случае 'arcade').

Внутри объекта arcade мы можем задать базовые параметры мира, такие как гравитация и режим отладки. Гравитация gravity: { y: 200 } будет постоянно тянуть объекты вниз. Флаг debug: true включает визуализацию физических тел (их границ), что невероятно полезно при разработке.

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

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

После настройки движка можно создавать объекты, которые будут ему подчиняться. В методе create сцены мы используем фабрику this.physics.add.image вместо обычного this.add.image. Эта фабрика автоматически создает спрайт и прикрепляет к нему тело Arcade Physics, делая объект управляемым физическим движком.

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

create ()
{
    const sprite1 = this.physics.add.image(100, 100, 'mushroom');
    const sprite2 = this.physics.add.image(400, 100, 'mushroom');
}

Управление свойствами тела: скорость и отскок

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

- setVelocity(100, 200) задает вектор скорости: 100 пикселей в секунду по оси X и 200 — по оси Y. Объект начнет двигаться вправо и вниз. - setBounce(1, 1) устанавливает упругость (коэффициент восстановления) по осям X и Y. Значение 1 означает идеально упругий отскок без потери энергии. Значение 0 — объект не отскочит. - setCollideWorldBounds(true) включает столкновение спрайта с границами игрового мира (определенными в config.width и config.height). Без этого объект может улететь за пределы экрана.

sprite1.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);
sprite2.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);

Добавление столкновений между объектами

Самая важная часть примера — это создание коллайдера. Без него физические тела будут проходить друг сквозь друга, несмотря на то, что они двигаются и отскакивают от границ мира.

Метод this.physics.add.collider(sprite1, sprite2) регистрирует в физическом движке правило: когда тела sprite1 и sprite2 пересекаются, они должны оттолкнуться друг от друга, как твердые объекты. Движок Arcade Physics автоматически вычисляет эти столкновения каждый кадр и корректирует позиции и скорости объектов.

Этот метод — основа для взаимодействия игрока с врагами, снарядов со стенами или любых других объектов в вашей игре.

this.physics.add.collider(sprite1, sprite2);

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

Всего за несколько шагов мы создали сцену с двумя физическими объектами, которые двигаются, отскакивают от стен и друг от друга. Это фундамент для бесчисленных игровых механик. Для экспериментов попробуйте: изменить гравитацию на { x: 100, y: 0 }, чтобы объекты сносило в сторону; задать спрайтам разную массу через setMass и посмотреть на разницу в столкновениях; или создать группу спрайтов (this.physics.add.group) и добавить коллайдер между группой и миром, чтобы симулировать падение множества объектов.