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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super({ key: "boot" });
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('rick', 'assets/pics/rick-and-morty-by-sawuinhaff-da64e7y.png');
    }

    create ()
    {
        this.cameras.main.fadeFrom(2000, Phaser.Math.Between(50, 255), Phaser.Math.Between(50, 255), Phaser.Math.Between(50, 255));

        this.add.image(400, 300, 'rick').setScale(0.7);
        this.cameras.main.on(Phaser.Cameras.Scene2D.Events.FADE_OUT_COMPLETE, () => {
            this.scene.restart();
        });

        //  Every time you click, fade the camera
        this.input.once('pointerdown', () => {

            //  Get a random color
            const red = Phaser.Math.Between(50, 255);
            const green = Phaser.Math.Between(50, 255);
            const blue = Phaser.Math.Between(50, 255);

            this.cameras.main.fade(2000, red, green, blue);

        });
    }
}

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

const game = new Phaser.Game(config);

game.scene.add('Boot', Example, true);

Разбираем структуру сцены

Код примера представляет собой одну сцену с ключом "boot". В Phaser сцена — это основной контейнер для игровой логики, разбитой на этапы: preload, create, update. В данном примере используется только preload и create, так как анимация построена на событиях, а не на непрерывном обновлении кадра.

class Example extends Phaser.Scene
{
    constructor ()
    {
        super({ key: "boot" });
    }

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

Эффект плавного появления и перезапуск по событию

В методе create происходит вся магия. Сначала камера плавно проявляется из случайного цвета, используя метод fadeFrom. Это создает эффект входа в сцену.

this.cameras.main.fadeFrom(2000, Phaser.Math.Between(50, 255), Phaser.Math.Between(50, 255), Phaser.Math.Between(50, 255));

Затем на камеру вешается обработчик события FADE_OUT_COMPLETE. Это событие срабатывает, когда эффект затемнения (fade) завершается. Внутри обработчика вызывается this.scene.restart(). Это ключевой метод, который полностью перезапускает текущую сцену: заново выполняются preload и create.

this.cameras.main.on(Phaser.Cameras.Scene2D.Events.FADE_OUT_COMPLETE, () => {
    this.scene.restart();
});

Таким образом, логика бесконечного цикла проста: сцена запускается, затемняется, и по завершении затемнения перезапускается сама себя, начиная с эффекта fadeFrom.

Инициирование цикла по клику мыши

Чтобы цикл начался, нужно инициировать затемнение. В примере это происходит по клику мыши. Обработчик pointerdown срабатывает один раз благодаря методу once. При клике генерируется случайный цвет для затемнения и запускается эффект fade.

this.input.once('pointerdown', () => {
    const red = Phaser.Math.Between(50, 255);
    const green = Phaser.Math.Between(50, 255);
    const blue = Phaser.Math.Between(50, 255);
    this.cameras.main.fade(2000, red, green, blue);
});

Именно вызов fade запускает цепочку событий: через 2 секунды сцена полностью затемнится в случайный цвет, сработает событие FADE_OUT_COMPLETE, и обработчик перезапустит сцену через this.scene.restart(). После перезапуска обработчик клика установится заново, и цикл можно будет повторить.

Конфигурация игры и добавление сцены

Это стандартный код инициализации игры Phaser 3. В конфиге задаются базовые параметры, такие как тип рендерера и размеры холста.

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600
};
const game = new Phaser.Game(config);

Затем созданный класс сцены добавляется в менеджер сцен игры под ключом 'Boot' и сразу запускается (третий аргумент true).

game.scene.add('Boot', Example, true);

Обратите внимание, что ключ, переданный в add, должен совпадать с ключом, указанным в конструкторе класса сцены ("boot"). В Phaser ключи сцен регистронезависимы.

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

Метод this.scene.restart() — мощный инструмент для создания игровых циклов без переключения между разными сценами. В связке с событиями камеры, такими как FADE_OUT_COMPLETE, он позволяет создавать плавные, кинематографичные переходы. Для экспериментов попробуйте: изменить условие перезапуска (например, по таймеру), добавить звуковые эффекты в моменты fadeIn/fadeOut, или использовать другие эффекты камеры (например, flash) перед вызовом restart.