О чем этот пример
В разработке игр часто требуется загружать и запускать сцены не все сразу, а по определённому сценарию: с задержкой, в ответ на действия игрока или по таймеру. В этой статье разберём практический пример динамического добавления сцен в Phaser 3, используя встроенный менеджер сцен и таймеры. Этот подход полезен для создания последовательных заставок, уровней, подгружаемых по частям, или любых сценариев, где контроль над жизненным циклом сцей критически важен.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Controller extends Phaser.Scene
{
constructor ()
{
super({ key: 'controller' });
}
preload ()
{
// this.load.setBaseURL('https://cdn.phaserfiles.com/v385');
this.load.script('demo', 'src/scenes/external scene/Demo.js');
}
create ()
{
var clone = 0;
this.time.addEvent({ delay: 2000, callback: function () {
this.scene.add('demo' + clone, Demo, true);
clone++;
}, callbackScope: this, repeat: 2 });
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
scene: [ Controller ]
};
const game = new Phaser.Game(config);
Архитектура примера: Главная сцена-контроллер
В этом примере используется особая архитектура. Вместо того чтобы сразу регистрировать все сцены в конфигурации игры, мы создаём одну главную сцену-контроллер. Её задача — управлять загрузкой и запуском других сцен. Это даёт нам полный контроль над процессом.
Основная сцена Controller указана как единственная в массиве scene при создании игры. Именно она будет запущена первой и будет отвечать за дальнейшую логику.
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
scene: [ Controller ] // Запускается только Controller
};
const game = new Phaser.Game(config);
Динамическая загрузка скрипта с классом сцены
Класс целевой сцены (Demo) не загружается изначально. Вместо этого мы динамически подгружаем его JavaScript-файл в методе preload() сцены-контроллера. Для этого используется метод this.load.script().
Важный нюанс: после такой загрузки класс Demo становится доступен глобально, и мы сможем ссылаться на него при создании сцены.
preload ()
{
// Динамически загружаем файл со скриптом сцены Demo
this.load.script('demo', 'src/scenes/external scene/Demo.js');
}
Создание сцен по таймеру с помощью Time Events
Сердце логики находится в методе create(). Мы используем систему событий времени Phaser (this.time.addEvent), чтобы с заданным интервалом создавать и запускать новые экземпляры сцены.
1. **Таймер**: Событие настраивается на задержку в 2000 мс, повторяется 2 раза (итого будет создано 3 сцены).
2. **Создание сцены**: В коллбэке используется `this.scene.add()`. Этот метод регистрирует новую сцену в менеджере сцен Phaser. Ключ сцены генерируется динамически (`'demo' + clone`), чтобы каждый экземпляр был уникальным.
3. **Немедленный запуск**: Третий параметр `true` в `this.scene.add()` указывает, что сцену нужно не только зарегистрировать, но и сразу запустить.
create ()
{
var clone = 0;
this.time.addEvent({
delay: 2000,
callback: function () {
// Регистрируем и сразу запускаем новую сцену
this.scene.add('demo' + clone, Demo, true);
clone++;
},
callbackScope: this,
repeat: 2
});
}
Ключевые API Phaser в этом примере
Для успешного использования этого паттерна важно понимать несколько ключевых методов API Phaser 3:
* `this.load.script(key, url)`: Загружает внешний JavaScript-файл и делает его содержимое доступным глобально.
* `this.time.addEvent(config)`: Создаёт повторяющееся или отложенное событие. Конфиг включает `delay`, `callback`, `callbackScope` и `repeat`.
* `this.scene.add(key, sceneClass, autoStart)`: Основной метод для динамической регистрации сцены. `key` — уникальный строковый идентификатор, `sceneClass` — ссылка на класс (в нашем случае глобальный `Demo`), `autoStart` — флаг немедленного запуска.
Использование callbackScope: this в конфиге таймера критически важно — оно гарантирует, что внутри коллбэка this будет указывать на экземпляр сцены Controller, и мы сможем корректно вызвать this.scene.add().
Что попробовать дальше
Динамическое создание сцен — мощный инструмент в Phaser 3 для построения сложной игровой логики. Разобранный паттерн позволяет отложить загрузку ресурсов и инициализацию до нужного момента, управлять порядком запуска уровней или мини-игр. Для экспериментов попробуйте:
1. Загружать сцены не по таймеру, а по клику игрока.
2. Передавать данные в новую сцену через её конструктор или метод init().
3. Останавливать (this.scene.stop()) или переключаться (this.scene.start()) между динамически созданными сценами.
