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

При разработке игр с физикой часто возникает необходимость удалять объекты со сцены. Phaser с плагином Matter.js предоставляет для этого метод `destroy()`, но его применение имеет важные нюансы. В этой статье разберем, как корректно удалять тела, чтобы избежать ошибок и утечек памяти, на примере уничтожения статической платформы по клику мыши.

Версия 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.add.image(325, -100, 'block');
        this.matter.add.image(400, 300, 'block');
        this.matter.add.image(450, 50, 'block');

        const platform = this.matter.add.image(400, 550, 'platform', null, { isStatic: true });

        console.log(platform);

        this.input.once('pointerup', () =>
        {

            platform.destroy();

        });
    }
}

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

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

В методе preload() мы загружаем два изображения, которые будут использоваться как физические тела. Обратите внимание на использование setBaseURL() – это удобно, если ваши ассеты хранятся в одном месте. В данном примере это удаленный репозиторий с примерами.

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() создаются четыре тела. Первые три – динамические блоки, которые упадут под действием гравитации. Четвертое тело – статическая платформа. Ключевые моменты:

1.  `this.matter.add.image` создает игровой объект (`Image`) с физическим телом Matter.js.
2.  Последний аргумент для платформы – `{ isStatic: true }` – делает тело неподвижным. Такие тела не подвержены силам и столкновениям, но могут быть уничтожены.
3.  Объект `platform` сохраняется в константу для последующего доступа.
create ()
{
    this.matter.add.image(325, -100, 'block');
    this.matter.add.image(400, 300, 'block');
    this.matter.add.image(450, 50, 'block');

    const platform = this.matter.add.image(400, 550, 'platform', null, { isStatic: true });
    console.log(platform);
}

Уничтожение тела по событию

Здесь происходит самое важное. Мы навешиваем одноразовый обработчик события клика (pointerup) на объект this.input. По срабатыванию события вызывается метод destroy() у объекта платформы.

Что делает destroy()?

1. Удаляет физическое тело (Matter.Body) из мира Matter.js. 2. Удаляет игровой объект (Phaser.GameObjects.Image) из текущей сцены и системы отображения. 3. Освобождает связанные с ним ресурсы.

Это предпочтительный способ удаления, а не простое скрытие объекта или отключение его физики.

this.input.once('pointerup', () =>
{
    platform.destroy();
});

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

Для работы с физикой Matter.js необходимо правильно настроить конфиг игры. В блоке physics указывается default: 'matter'. Это инициализирует плагин Matter.js и делает его методы доступными через this.matter в сцене.

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

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

Метод destroy() – это стандартный и безопасный способ полного удаления игрового объекта вместе с его физическим телом в Phaser. Для экспериментов попробуйте: вызвать destroy() у динамического блока (он исчезнет при падении), удалить несколько тел по разным условиям (например, при выходе за границы экрана) или создать новую платформу после уничтожения старой.