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

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

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

Живой запуск

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

Исходный код


class DemoA extends Phaser.Scene
{
    constructor ()
    {
        super({ key: 'demoA', active: true });
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('picA', 'assets/pics/lance-overdose-loader-eye.png');
    }

    create ()
    {
        this.add.image(400, 300, 'picA');

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

            this.scene.sendToBack();

        }, this);
    }
}

class DemoB extends Phaser.Scene
{
    constructor ()
    {
        super({ key: 'demoB', active: true });
    }

    preload ()
    {
        // this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('picB', 'assets/pics/sukasuka-chtholly.png');
    }

    create ()
    {
        this.add.image(400, 500, 'picB');
    }
}

class DemoC extends Phaser.Scene
{
    constructor ()
    {
        super({ key: 'demoC', active: true });
    }

    preload ()
    {
        // this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('picC', 'assets/pics/titan-mech.png');
    }

    create ()
    {
        this.add.image(300, 300, 'picC');
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    scene: [ DemoB, DemoC, DemoA ]
};

const game = new Phaser.Game(config);

Что делает пример?

В примере создаются три независимые сцены (DemoA, DemoB, DemoC), каждая из которых загружает и отображает свою картинку. Изначально сцены активны одновременно и отрисовываются в порядке, указанном в массиве конфигурации игры: [ DemoB, DemoC, DemoA ]. Это значит, что DemoA будет поверх всех.

По клику мыши на сцене DemoA вызывается метод this.scene.sendToBack(), который перемещает эту сцену в самый низ стека отрисовки. Визуально это приводит к тому, что картинка из DemoA "проваливается" под изображения из двух других сцен.

Стек сцен и порядок отрисовки

Phaser управляет сценами как стеком. Сцена, добавленная последней или находящаяся выше в списке конфигурации, отрисовывается поверх остальных. Ключевой параметр active: true в конструкторе каждой сцены позволяет им запускаться и работать одновременно.

Посмотрим на порядок в конфиге:

scene: [ DemoB, DemoC, DemoA ]

Это означает, что DemoB будет отрисована первой (самый нижний слой), затем DemoC поверх неё, и, наконец, DemoA — поверх всех. Именно поэтому в начале работы примера картинка из DemoA перекрывает остальные.

Ключевой метод: `scene.sendToBack()`

Метод sendToBack() — часть API менеджера сцен (this.scene). Он перемещает вызывающую сцену в самый низ стека отрисовки. В нашем примере он привязан к событию клика.

Код в сцене DemoA:

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

Здесь this.input.once регистрирует обработчик на одно срабатывание события клика (pointerdown). При срабатывании вызывается this.scene.sendToBack(), и сцена DemoA мгновенно отправляется за DemoB и DemoC. Важно передать контекст this как третий аргумент, чтобы внутри функции-колбэка this ссылалось на экземпляр сцены, а не на глобальный объект.

Структура кода: независимые сцены

Каждая сцена — это отдельный класс, расширяющий Phaser.Scene. Они не знают друг о друге, что делает архитектуру чистой и модульной.

Пример объявления сцены DemoA:

class DemoA extends Phaser.Scene
{
    constructor ()
    {
        super({ key: 'demoA', active: true });
    }
    // ... preload и create ...
}

Ключ (key) — уникальный идентификатор сцены. Параметр active: true в конструкторе позволяет сцене запуститься сразу вместе с игрой. Методы preload и create стандартны: в preload загружается изображение по заданному URL, а в create оно добавляется на сцену с помощью this.add.image(x, y, key).

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

Метод sendToBack() — простой, но эффективный способ динамического управления визуальными слоями в игре. Вы можете использовать этот подход для скрытия игрового мира под меню паузы, переключения между режимами (например, карта и бой) или создания сложных UI-композиций. Для экспериментов попробуйте связать вызов метода с другими событиями (таймер, коллизия), использовать парный метод bringToTop() или управлять сценами по их ключам через this.scene.moveDown('key').