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

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

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    static3;
    static2;
    static1;
    sprite;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('bar', 'assets/sprites/healthbar.png');
        this.load.image('mushroom', 'assets/sprites/mushroom2.png');
    }

    create ()
    {
        this.sprite = this.physics.add.image(100, 100, 'mushroom');

        this.static1 = this.physics.add.staticImage(400, 100, 'bar');
        this.static2 = this.physics.add.staticImage(100, 400, 'bar');
        this.static3 = this.physics.add.staticImage(500, 300, 'bar');

        this.sprite.body.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);
    }

    update ()
    {
        this.physics.world.collide(this.sprite, [ this.static1, this.static2, this.static3 ]);
    }
}

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

const game = new Phaser.Game(config);

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

Класс Example расширяет Phaser.Scene. В нем объявлены свойства для хранения ссылок на спрайты: static1, static2, static3 для статических тел и sprite для динамического.

В методе preload() задается базовый URL для загрузки и загружаются два изображения: спрайт гриба (mushroom) и изображение для статической полосы (bar).

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('bar', 'assets/sprites/healthbar.png');
    this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}

Создание физических тел в create()

Метод create() инициализирует все игровые объекты. Динамическое тело создается с помощью this.physics.add.image. Это спрайт, на который воздействует гравитация и который может двигаться.

this.sprite = this.physics.add.image(100, 100, 'mushroom');

Статические тела создаются методом this.physics.add.staticImage. Они сразу добавляются в физический мир как неподвижные объекты.

this.static1 = this.physics.add.staticImage(400, 100, 'bar');
this.static2 = this.physics.add.staticImage(100, 400, 'bar');
this.static3 = this.physics.add.staticImage(500, 300, 'bar');

Затем для динамического спрайта настраиваются физические свойства: задается начальная скорость, упругость (отскок) и включение столкновений с границами мира.

this.sprite.body.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);

Обработка столкновений в update()

Метод update() вызывается каждый кадр игры. В нем проверяются столкновения между динамическим спрайтом и массивом статических тел с помощью this.physics.world.collide. Phaser автоматически обрабатывает физику столкновения и отскока для этих объектов.

update ()
{
    this.physics.world.collide(this.sprite, [ this.static1, this.static2, this.static3 ]);
}

Конфигурация игры и физики

Объект config содержит основные настройки игры. Ключевой раздел — physics. Здесь активируется система Arcade Physics, задается гравитация и включается отладочный режим, который рисует контуры физических тел.

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

Игра инициируется созданием нового экземпляра Phaser.Game с этой конфигурацией.

const game = new Phaser.Game(config);

Отличие staticImage от обычного image

Главное отличие между this.physics.add.image и this.physics.add.staticImage — в типе создаваемого физического тела. - **Динамическое тело** (image) реагирует на силы: гравитацию, скорость, импульсы. Его можно двигать методами физики. - **Статическое тело** (staticImage) имеет массу, но его позиция фиксирована физическим движком. Оно не падает под действием гравитации и не сдвигается при столкновении, что делает его идеальным для платформ и стен.

Использование статических тел для неподвижных объектов — это оптимизация. Движок тратит меньше ресурсов на расчет их движения.

Практические советы

1. **Отладка:** Включите debug: true в конфиге Arcade Physics, чтобы видеть контуры тел. Синие контуры — динамические, зеленые — статические. 2. **Группы статических тел:** Если статических объектов много, создайте физическую группу (this.physics.add.staticGroup) для более эффективного управления и проверки столкновений. 3. **Изменение статического тела:** Если вам все же нужно сдвинуть статический объект после создания, вызовите для него метод body.updateFromGameObject(). Не забывайте, что это требует пересчета в движке. 4. **Производительность:** Столкновения между динамическим телом и массивом статических (collide(sprite, array)) работают эффективно. Для сложных сцен используйте методы коллизии с группами.

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

Использование статических тел — простой и производительный способ создания неподвижных препятствий и платформ в играх на Phaser. Они идеально подходят для уровня, декораций и любых объектов, которые не должны двигаться под действием физики. **Идеи для экспериментов:** 1. Замените массив статических тел на staticGroup и проверьте столкновения с группой. 2. Попробуйте изменить гравитацию на { x: 100, y: 0 }, чтобы создать эффект "бокового" притяжения. 3. Добавьте несколько динамических спрайтов и заставьте их сталкиваться друг с другом и со статическими объектами.