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

В Phaser управление сценами — ключевая концепция организации игровой логики. Часто бывает необходимо добавить новую сцену уже после создания основного объекта `Game`. Этот подход полезен для модульной загрузки игровых уровней, меню или мини-игр по требованию, что позволяет экономить ресурсы и строить более гибкую архитектуру проекта. В статье разберем, как правильно это сделать, используя метод `game.scene.add()`.

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

Живой запуск

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

Исходный код


class MyScene extends Phaser.Scene {

    constructor (config)
    {
        super(config);
    }

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

    create (data)
    {
        this.face = this.add.image(data.x, data.y, 'face');
    }

}

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600
};

var game = new Phaser.Game(config);

game.scene.add('myScene', MyScene, true, { x: 400, y: 300 });

Создание базовой конфигурации и игры

Перед добавлением сцен необходимо создать экземпляр игры с базовой конфигурацией. В этом примере конфигурация минимальна: заданы тип рендерера, родительский контейнер в DOM и размеры холста.

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600
};

var game = new Phaser.Game(config);

После выполнения этого кода объект game становится точкой входа для управления всеми аспектами Phaser, включая менеджер сцен.

Определение пользовательской сцены

Сцена в Phaser — это класс, расширяющий Phaser.Scene. В нем определяются ключевые жизненные циклы, такие как preload() для загрузки ассетов и create() для их создания на сцене.

class MyScene extends Phaser.Scene {
    constructor (config) {
        super(config);
    }

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

    create (data) {
        this.face = this.add.image(data.x, data.y, 'face');
    }
}

Обратите внимание: метод create принимает параметр data. Через него можно передавать данные извне в момент запуска сцены, например, координаты для размещения спрайта.

Добавление и запуск сцены после инициализации игры

Метод game.scene.add() регистрирует класс сцены в менеджере сцен игры. Его сигнатура позволяет не только добавить сцену, но и сразу её запустить, передав начальные данные.

game.scene.add('myScene', MyScene, true, { x: 400, y: 300 });

Разберем аргументы: 1. 'myScene' — уникальный ключ (идентификатор) сцены. 2. MyScene — класс (конструктор) сцены. 3. true — флаг автозапуска. Если true, сцена запускается немедленно после добавления. 4. { x: 400, y: 300 } — объект данных, который будет передан в метод create сцены. В нашем примере это координаты для изображения.

Именно этот вызов позволяет динамически расширять игровой мир после того, как игра уже была создана.

Практическое применение и передача данных

Передача данных через game.scene.add() — мощный механизм для параметризации сцен. В примере координаты `xиy` из объекта данных используются для позиционирования изображения.

create (data) {
    // data содержит { x: 400, y: 300 }
    this.face = this.add.image(data.x, data.y, 'face');
}

Это позволяет переиспользовать один и тот же класс сцены для отображения контента в разных позициях или с разными настройками, делая код более универсальным. Например, можно передавать тип врага, номер уровня или цвет фона.

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

Динамическое добавление сцен через game.scene.add() — основа для создания модульных и масштабируемых игр на Phaser. Вы можете загружать уровни по мере необходимости, реализовывать сложные переходы между состояниями игры и эффективно управлять памятью. Для экспериментов попробуйте: добавлять несколько экземпляров одной сцены с разными данными, выносить загрузку ассетов в отдельную сцену-загрузчик или реализовать систему ленивой подгрузки игровых зон.