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

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

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

Живой запуск

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

Исходный код



const sceneConfigA = {
    key: 'sceneA',
    create: createA,
    pack: {
        files: [
            { type: 'image', key: 'face', url: 'assets/pics/bw-face.png' }
        ]
    }
};

const sceneConfigB = {
    key: 'sceneB',
    create: createB,
    pack: {
        files: [
            { type: 'image', key: 'logo', url: 'assets/pics/monika-krawinkel-amberstar-title.png' }
        ]
    }
};

function createA ()
{
    this.add.image(400, 300, 'face');

    this.input.on('pointerdown', () =>
    {
        this.input.stopPropagation();
        this.scene.switch('sceneB');
    });
}

function createB ()
{
    this.add.image(400, 300, 'logo');

    this.input.on('pointerdown', () =>
    {
        this.input.stopPropagation();
        this.scene.switch('sceneA');
    });
}

const gameConfig = {
    type: Phaser.CANVAS,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: [ sceneConfigA, sceneConfigB ]
};

const game = new Phaser.Game(gameConfig);

Конфигурация сцен: разделяем ресурсы и логику

В Phaser сцена настраивается через объект конфигурации. В примере создано две таких конфигурации: sceneConfigA и sceneConfigB. Ключевое поле key задаёт уникальное имя сцены, по которому мы будем к ней обращаться.

Поле pack позволяет предзагрузить ассеты (изображения, аудио) непосредственно для этой сцены. Это удобно для модульности: ресурсы для меню загружаются с меню, а для уровня — с уровнем.

Функция create, указанная в поле create, будет вызвана автоматически, когда сцена будет создана движком. В ней выполняется начальная настройка.

const sceneConfigA = {
    key: 'sceneA',
    create: createA,
    pack: {
        files: [
            { type: 'image', key: 'face', url: 'assets/pics/bw-face.png' }
        ]
    }
};

Создание графики и обработка ввода

Внутри функций createA и createB происходит отрисовка изображения на сцене с помощью метода this.add.image(). Первые два аргумента — координаты X и Y, третий — ключ изображения, объявленный в pack.

Затем настраивается обработчик события клика (pointerdown). Вызов this.input.stopPropagation() предотвращает потенциальное "всплытие" события, если бы элементы ввода были вложены друг в друга (хотя в данном примере это не требуется).

function createA ()
{
    this.add.image(400, 300, 'face');

    this.input.on('pointerdown', () =>
    {
        this.input.stopPropagation();
        this.scene.switch('sceneB');
    });
}

Магия метода `this.scene.switch()`

Сердце примера — вызов this.scene.switch() внутри обработчика клика. Этот метод мгновенно переключает активную сцену.

Важно понимать его поведение: - Текущая сцена **не уничтожается**. Она переходит в состояние паузы (SCENE.SLEEPING). - Сцена, на которую происходит переключение, **пробуждается** (SCENE.RUNNING), если она была создана ранее, либо создаётся и запускается. - Состояние сцены (позиции объектов, переменные) сохраняется. Это идеально для переключения между, например, игровым уровнем и инвентарём.

В нашем примере вызов this.scene.switch('sceneB') из сцены A делает активной сцену B, и наоборот.

this.scene.switch('sceneB');

Инициализация игры с несколькими сценами

Чтобы движок знал о существовании наших сцен, их конфигурации необходимо передать в главную конфигурацию игры (gameConfig) в поле scene. Оно принимает массив. Порядок в массиве имеет значение: первая сцена в списке будет запущена автоматически при старте игры.

const gameConfig = {
    type: Phaser.CANVAS,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: [ sceneConfigA, sceneConfigB ] // Запустится sceneA
};

const game = new Phaser.Game(gameConfig);

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

Метод switch() предоставляет простой и эффективный способ управления несколькими экранами в игре, сохраняя их состояние. Это базовый кирпичик для построения сложной навигации. **Идеи для экспериментов:** 1. Добавьте третью сцену и создайте "циклический" переключатель между всеми. 2. Загрузите разные звуки в pack каждой сцены и воспроизводите их при переключении. 3. Используйте this.scene.start() вместо switch() и посмотрите, как полностью перезапускается сцена (её состояние сбросится).