О чем этот пример
Управление сценами — ключевой навык в разработке игр на Phaser. Умение ставить сцены на паузу и возобновлять их позволяет создавать сложные игровые механики, например, меню паузы, диалоговые окна или мини-игры, не прерывая основной геймплей. В этой статье мы разберем практический пример с двумя сценами, где одна ставится на паузу, а другая запускается, и посмотрим, как правильно обрабатывать события `pause` и `resume` для плавного переключения. Это особенно полезно для игр, где нужно временно приостановить физику, анимацию или логику, не выгружая сцену из памяти, что экономит ресурсы и упрощает управление состоянием игры.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class SceneA extends Phaser.Scene
{
constructor ()
{
super({ key: 'sceneA' });
this.pic;
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('arrow', 'assets/sprites/longarrow.png');
}
create ()
{
this.pic = this.add.image(400, 300, 'arrow').setOrigin(0, 0.5);
this.input.once('pointerup', function ()
{
this.scene.pause();
this.scene.launch('sceneB');
}, this);
this.events.on('pause', () =>
{
console.log('Scene A paused');
});
this.events.on('resume', () =>
{
console.log('Scene A resumed');
});
}
update (time, delta)
{
this.pic.rotation += 0.01;
}
}
class SceneB extends Phaser.Scene
{
constructor ()
{
super({ key: 'sceneB' });
}
preload ()
{
// this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('face', 'assets/pics/bw-face.png');
}
create ()
{
this.add.image(400, 300, 'face').setAlpha(0.5);
this.input.once('pointerdown', function ()
{
this.scene.resume('sceneA');
}, this);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: [ SceneA, SceneB ]
};
const game = new Phaser.Game(config);
Настройка сцены A: основа игры
Сцена A (SceneA) выступает в роли основной игровой сцены. В ней загружается спрайт стрелки, который непрерывно вращается в методе update. Это имитирует активный игровой процесс.
Ключевые моменты:
- В preload загружается изображение стрелки с удаленного URL.
- В create создается спрайт стрелки, устанавливается его точка вращения, и добавляется обработчик клика мыши.
- Обработчик клика использует this.scene.pause() для приостановки текущей сцены и this.scene.launch('sceneB') для запуска сцены B.
class SceneA extends Phaser.Scene {
constructor() {
super({ key: 'sceneA' });
this.pic;
}
preload() {
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('arrow', 'assets/sprites/longarrow.png');
}
create() {
this.pic = this.add.image(400, 300, 'arrow').setOrigin(0, 0.5);
this.input.once('pointerup', function() {
this.scene.pause();
this.scene.launch('sceneB');
}, this);
}
update(time, delta) {
this.pic.rotation += 0.01;
}
}
Обработка событий паузы и возобновления
Phaser позволяет отслеживать изменения состояния сцены через события. В SceneA мы подписываемся на события pause и resume, чтобы выполнять действия при приостановке и возобновлении. Это полезно для управления звуками, анимациями или логикой, зависящей от активности сцены.
- Событие `pause` срабатывает, когда вызывается `this.scene.pause()`.
- Событие `resume` срабатывает при вызове `this.scene.resume('sceneA')` из другой сцены.
- В примере мы просто логируем эти события в консоль, но в реальном проекте здесь можно приостановить таймеры или физику.
this.events.on('pause', () => {
console.log('Scene A paused');
});
this.events.on('resume', () => {
console.log('Scene A resumed');
});
Важно: метод update в SceneA автоматически перестает вызываться при паузе и возобновляется при resume, что видно по остановке вращения стрелки.
Создание сцены B: временный экран
Сцена B (SceneB) представляет собой временный экран, например, меню или диалоговое окно. Она загружает другое изображение и отображает его с полупрозрачностью. Её задача — быть активной, пока основная сцена на паузе.
- В create добавляется полупрозрачное изображение и обработчик клика мыши.
- Обработчик вызывает this.scene.resume('sceneA'), чтобы возобновить SceneA. При этом SceneB автоматически завершится, так как она была запущена через launch и не является постоянной.
class SceneB extends Phaser.Scene {
constructor() {
super({ key: 'sceneB' });
}
preload() {
this.load.image('face', 'assets/pics/bw-face.png');
}
create() {
this.add.image(400, 300, 'face').setAlpha(0.5);
this.input.once('pointerdown', function() {
this.scene.resume('sceneA');
}, this);
}
}
Заметьте: SceneB не имеет метода update, так как ей не требуется непрерывная логика.
Конфигурация игры и запуск сцен
Игра настраивается через объект config, где обе сцены передаются в массиве scene. Phaser автоматически инициализирует их в порядке указания, но активной будет только первая — SceneA.
- SceneA запускается первой и становится активной.
- При паузе SceneA и запуске SceneB управление переходит к SceneB, но SceneA остается в памяти с замороженным состоянием.
- После возобновления SceneA управление возвращается к ней, а SceneB удаляется.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: [SceneA, SceneB]
};
const game = new Phaser.Game(config);
Этот подход позволяет легко управлять стеками сцен без перезагрузки ресурсов.
Что попробовать дальше
Пауза и возобновление сцен в Phaser — мощный инструмент для создания гибкой архитектуры игры. Вы можете использовать это для пауз, диалоговых окон или мини-игр, не нарушая основной геймплей. Экспериментируйте: добавьте в SceneB кнопку для возврата в SceneA, используйте this.scene.stop('sceneB') для явного завершения сцены или подключайте события pause для сохранения состояния игры. Попробуйте управлять несколькими сценами одновременно через this.scene.bringToTop().
