О чем этот пример
Перезапуск сцены — это мощный инструмент для сброса состояния игры без перезагрузки всей страницы. В примере с физикой 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() — это быстрый способ полного сброса состояния сцены. Он полезен не только для демо, но и для игровых механик: перезапуск уровня после поражения, сброс головоломки, рестарт мини-игры. Для экспериментов попробуйте
- Передавать данные в метод
restart()для условного рестарта - Использовать его не по клику, а по таймеру или выполнению условия
- Сравнить его работу с
this.scene.start()при переключении между разными сценами
