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

Перезапуск сцены — это мощный инструмент для сброса состояния игры без перезагрузки всей страницы. В примере с физикой Matter.js это позволяет мгновенно воссоздать все объекты с их начальными параметрами, что идеально подходит для демонстраций, отладки или реализации функции "перезапустить уровень". Вы научитесь использовать `this.scene.restart()` эффективно и поймёте, как он взаимодействует с физическим миром.

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

Живой запуск

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

Исходный код


class SceneA extends Phaser.Scene
{
    constructor ()
    {
        super({ key: 'sceneA' });
    }

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

    create ()
    {
        this.matter.world.setBounds(0, 0, 800, 600, 32, true, true, false, true);

        for (let i = 0; i < 64; i++)
        {
            const ball = this.matter.add.image(Phaser.Math.Between(100, 700), Phaser.Math.Between(-600, 0), 'ball1');
            ball.setCircle();
            ball.setFriction(0.005);
            ball.setBounce(1);
        }

        this.input.once('pointerdown', function (event)
        {

            this.scene.restart();

        }, this);
    }
}


const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#000000',
    parent: 'phaser-example',
    scene: [ SceneA ],
    physics: {
        default: 'matter',
        matter: {
            setBounds: {
                x: 0,
                y: 0,
                width: 800,
                height: 600,
                thickness: 64
            },
            enableSleeping: true
        }
    }
};

const game = new Phaser.Game(config);

Инициализация сцены и загрузка ассетов

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

class SceneA extends Phaser.Scene
{
    constructor ()
    {
        super({ key: 'sceneA' });
    }

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

Создание физического мира и объектов

В методе create сначала настраиваются границы физического мира Matter.js. Важно: в коде конфига также заданы границы (setBounds), но вызов this.matter.world.setBounds в сцене переопределяет их, создавая стены со всех сторон, кроме нижней. Затем в цикле создаётся 64 физических мяча. Каждый мяч — это Matter.Image, которому задаётся круглая форма, низкое трение и упругость 1 (абсолютно упругий удар). Мячи появляются в случайных позициях по горизонтали и выше видимой области, чтобы падали сверху.

create ()
{
    this.matter.world.setBounds(0, 0, 800, 600, 32, true, true, false, true);

    for (let i = 0; i < 64; i++)
    {
        const ball = this.matter.add.image(Phaser.Math.Between(100, 700), Phaser.Math.Between(-600, 0), 'ball1');
        ball.setCircle();
        ball.setFriction(0.005);
        ball.setBounce(1);
    }

Механизм перезапуска по клику

Ключевая часть примера — обработчик события pointerdown. Он срабатывает один раз при первом клике (благодаря once). Внутри вызывается метод this.scene.restart(). Этот вызов полностью уничтожает текущую инстанцию сцены (включая все созданные в create объекты и слушатели событий), а затем снова запускает её жизненный цикл: init, preload, create и т.д. Всё начинается заново.

this.input.once('pointerdown', function (event)
    {
        this.scene.restart();
    }, this);
}

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

Конфиг игры включает важные настройки для физики. Указывается движок matter по умолчанию. В блоке matter задаются глобальные границы мира (которые, как мы видели, можно переопределить в сцене) и включается enableSleeping — это оптимизация, которая "усыпляет" неподвижные тела, экономя ресурсы процессора.

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#000000',
    parent: 'phaser-example',
    scene: [ SceneA ],
    physics: {
        default: 'matter',
        matter: {
            setBounds: {
                x: 0,
                y: 0,
                width: 800,
                height: 600,
                thickness: 64
            },
            enableSleeping: true
        }
    }
};

const game = new Phaser.Game(config);

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

Метод this.scene.restart() — это быстрый способ полного сброса состояния сцены. Он полезен не только для демо, но и для игровых механик: перезапуск уровня после поражения, сброс головоломки, рестарт мини-игры. Для экспериментов попробуйте

  1. Передавать данные в метод restart() для условного рестарта
  2. Использовать его не по клику, а по таймеру или выполнению условия
  3. Сравнить его работу с this.scene.start() при переключении между разными сценами