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

Управление сценами — ключевой навык в разработке игр на 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().