О чем этот пример
При создании сложных игр с интерфейсами, меню или наложениями часто требуется динамически менять порядок отрисовки сцен. Стандартный порядок, заданный в конфигурации, не всегда подходит для интерактивных сценариев. В этой статье разберем, как использовать метод `scene.bringToTop()` для управления стэком сцен на примере из официальной документации. Понимание работы со сценами — ключ к созданию чистого и управляемого кода в Phaser. Мы рассмотрим, как правильно инициализировать несколько активных сцен и программно выводить нужную из них на передний план, что особенно полезно для реализации пауз, диалоговых окон или сложных UI/эффектов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
// Needless to say, RICK AND MORTY is a trademark of Cartoon Network, Inc.,
class Controller extends Phaser.Scene {
constructor ()
{
super('Controller');
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/pics/purple-dots.png');
}
create ()
{
this.add.image(400, 300, 'bg');
// This will bring the Logo Scene to the top of the Scene List
this.scene.bringToTop('Logo');
}
}
class Rick extends Phaser.Scene {
constructor ()
{
super({ key: 'Rick', active: true });
}
preload ()
{
// this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('rick', 'assets/pics/guard-rick.png');
}
create ()
{
this.add.image(750, 600, 'rick').setOrigin(1);
}
}
class Morty extends Phaser.Scene {
constructor ()
{
super({ key: 'Morty', active: true });
}
preload ()
{
// this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('morty', 'assets/pics/morty.png');
}
create ()
{
this.add.image(250, 300, 'morty');
}
}
class Logo extends Phaser.Scene {
constructor ()
{
super({ key: 'Logo', active: true });
}
preload ()
{
// this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('logo', 'assets/pics/rick-and-morty-logo.png');
}
create ()
{
this.add.image(400, 450, 'logo');
}
}
let config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: [ Controller, Logo, Morty, Rick ]
};
let game = new Phaser.Game(config);
Анатомия примера: четыре сцены в одном проекте
В примере создается одна игра с четырьмя одновременно активными сценами. Каждая сцена отвечает за свой визуальный элемент: фон, логотип и двух персонажей.
Ключевой момент — настройка сцен в массиве scene конфигурации игры. Порядок в этом массиве определяет начальный порядок отрисовки (снизу вверх). Однако, если сцены созданы с флагом active: true, они рендерятся одновременно, и их порядок в стеке можно менять динамически.
let config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: [ Controller, Logo, Morty, Rick ]
};
Создание сцен: флаг active и ключ key
Три сцены (Logo, Morty, Rick) создаются с одинаковыми параметрами в конструкторе. Параметр active: true указывает, что сцена должна запуститься сразу же при старте игры. Параметр key — это уникальный строковый идентификатор сцены, по которому мы сможем к ней обращаться из других сцен.
constructor ()
{
super({ key: 'Logo', active: true });
}
Сцена Controller объявлена иначе. Она не активна изначально и будет запущена явно, так как указана первой в массиве конфигурации. Ее роль — управление порядком других сцен.
Метод bringToTop: как вывести сцену на передний план
Вся магия управления порядком происходит в сцене Controller. В ее методе create() после загрузки фона вызывается одна критически важная команда.
create ()
{
this.add.image(400, 300, 'bg');
// This will bring the Logo Scene to the top of the Scene List
this.scene.bringToTop('Logo');
}
Метод this.scene.bringToTop('Logo') ищет в системе сцен экземпляр с ключом 'Logo' и перемещает его на самый верх стека отрисовки. Это означает, что все графические объекты сцены Logo (в данном случае изображение с логотипом) будут отрисованы поверх всех объектов сцен, которые находятся ниже в стеке (Morty и Rick). Без этого вызова логотип был бы скрыт за изображениями персонажей.
Визуальный результат и порядок слоев
Давайте представим итоговый порядок сцен после выполнения кода:
1. **Нижний слой:** Controller (фиолетовый фон). Он был запущен первым.
2. **Средний слой:** Rick и Morty. Они активны с самого начала и отрисованы в порядке, обратном массиву конфигурации (сначала Rick, потом Morty, но так как они на одном уровне, важен только факт, что они ниже Logo).
3. **Верхний слой:** Logo. Благодаря вызову bringToTop, эта сцена оказалась поверх всех, и ее логотип теперь виден целиком.
Если убрать строку с bringToTop, логотип будет отрисован согласно начальному порядку из массива scene, то есть, скорее всего, окажется под персонажами и будет частично или полностью скрыт.
Практическое применение: меню, диалоги, окна
Метод bringToTop — это не просто инструмент для статичной композиции, а основа для интерактивности.
* **Всплывающее меню паузы:** У вас может быть сцена Game (игровой мир) и сцена PauseMenu (меню). При нажатии ESC вы запускаете сцену PauseMenu и вызываете для нее bringToTop, чтобы она перекрыла игру.
* **Диалоговые окна:** Создайте сцену Dialog. Каждый раз при начале диалога запускайте ее и выводите на передний план поверх игровой сцены.
* **Система уведомлений:** Сцена Notification может появляться поверх всего интерфейса для показа важных сообщений.
Важно помнить, что bringToTop работает только с уже запущенными (active) сценами. Для неактивных сцен сначала используйте this.scene.launch('YourSceneKey').
Что попробовать дальше
Динамическое управление порядком сцен через bringToTop() — мощный механизм в Phaser 3 для создания многослойных интерфейсов и игровых состояний. Он позволяет разделять логику разных частей игры (UI, мир, эффекты) по разным сценам, сохраняя при этом полный контроль над их видимостью.
**Идеи для экспериментов:**
1. Добавьте в сцену Controller обработчик клика мыши, который по очереди выводит на передний план сцены Rick, Morty и Logo.
2. Создайте сцену-«затемнитель» (Dim) с полупрозрачным черным прямоугольником. Используйте bringToTop, чтобы затемнять фон при показе меню паузы, создавая визуальную глубину.
3. Изучите другие методы управления сценами: sendToBack(), moveUp(), moveDown() — и создайте простой визуальный редактор порядка слоев.
