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

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

Версия 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.bringToTop();

        }, 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: [ DemoA, DemoB, DemoC ]
};

const game = new Phaser.Game(config);

Что такое стек сцен и почему важен порядок?

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

Представьте себе стопку прозрачных слайдов: изображение на нижнем слайде будет перекрыто изображениями на верхних. Порядок сцен в массиве определяет их изначальное положение в этой стопке. Метод bringToTop позволяет взять любой слайд (сцену) и переместить его на самый верх.

Анализ кода: инициализация и структура

Давайте посмотрим на конфигурацию игры и конструкторы сцен. Все три сцены создаются с флагом active: true, что означает их одновременную активность и рендеринг.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    scene: [ DemoA, DemoB, DemoC ] // Исходный порядок рендеринга
};
constructor ()
{
    super({ key: 'demoA', active: true });
}

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

Ключевой триггер: обработка ввода

Вся магия происходит в сцене DemoA. В её методе create мы навешиваем одноразовый обработчик события клика (pointerdown).

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

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

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

Как работает метод bringToTop

Метод bringToTop() вызывается для менеджера сцен (this.scene) текущей сцены (DemoA). Этот метод ищет сцену, из которой он был вызван, в общем списке активных сцен игры и перемещает её на последнюю позицию в этом списке.

До клика порядок рендеринга: [DemoA, DemoB, DemoC]. После вызова this.scene.bringToTop() внутри DemoA порядок изменится на: [DemoB, DemoC, DemoA]. Следовательно, изображение из DemoA (lance-overdose-loader-eye.png), которое было внизу, теперь окажется поверх изображений из DemoB и DemoC.

Это чисто визуальное изменение порядка отрисовки. Логика и обновление (update) сцен остаются нетронутыми.

Практическое применение и аналоги

bringToTop идеально подходит для: * Всплывающих окон (пауза, инвентарь, диалоги). * Переключения HUD или слоев интерфейса. * Эффектов, которые должны быть поверх всего (затемнение экрана, вспышка).

Phaser Scene Manager предоставляет и другие методы для управления порядком: * sendToBack() — перемещает сцену в самый низ стека. * moveUp() — перемещает сцену на одну позицию выше. * moveDown() — перемещает сцену на одну позицию ниже.

// Примеры других методов управления порядком
this.scene.sendToBack(); // Отправить сцену на задний план
this.scene.moveUp();     // Поднять на один уровень
this.scene.moveDown();   // Опустить на один уровень

Эти методы дают точный контроль над визуальной иерархией вашей игры.

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

Метод bringToTop — это простой и эффективный инструмент для динамического управления визуальным порядком сцен в Phaser. Он позволяет реагировать на действия игрока и создавать многослойные композиции. Для экспериментов попробуйте: 1. Вызвать bringToTop из разных сцен по разным условиям (не только по клику). 2. Скомбинировать его с методами паузы (this.scene.pause()) и возобновления (this.scene.resume()) для сложного управления состоянием интерфейса. 3. Создать систему модальных окон, где новое окно автоматически вызывается на верхний план, а предыдущее затемняется.