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

В разработке игр часто требуется обмениваться информацией между различными частями игры, например, передавать результаты уровня, состояние игрока или параметры загрузки. В Phaser 3 для этого предусмотрен удобный механизм передачи данных при запуске сцен. Эта статья покажет, как правильно использовать параметры `init`, `create` и метод `scene.start()` для создания модульной и гибкой архитектуры вашей игры.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    constructor()
    {
        super({ key: 'test', active: false });
    }

    init (data)
    {
        this.png = data.image;
    }

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

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


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

const game = new Phaser.Game(config);
game.scene.start('test', { image: 'titan-mech.png', x: 400, y: 300 });

Зачем передавать данные между сценами?

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

Анатомия сцены, готовой к приёму данных

Ключевыми точками входа для получения данных в сцене являются методы init() и create(). Оба получают один аргумент — объект data.

class Example extends Phaser.Scene
{
    constructor()
    {
        super({ key: 'test', active: false });
    }

    init (data)
    {
        this.png = data.image;
    }

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

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

Метод init() выполняется до preload(). Здесь удобно сохранить переданные данные в свойства сцены (например, this.png), чтобы использовать их на этапе загрузки. Метод create() получает тот же объект данных, и здесь мы используем его для позиционирования изображения. Разделение логики: init для настройки, create для создания объектов.

Как запустить сцену с данными

Передача данных происходит в момент старта сцены с помощью метода game.scene.start().

const game = new Phaser.Game(config);
game.scene.start('test', { image: 'titan-mech.png', x: 400, y: 300 });

Вторым аргументом мы передаём объект. Его свойства (image, `x,y) будут доступны внутри сцены вinit(data)иcreate(data)какdata.image,data.xиdata.y`. Это прямой и эффективный способ инициализировать сцену с нужными параметрами.

Практические сценарии использования

1. **Динамическая загрузка ресурсов:** Как в примере, вы можете передавать имя файла изображения, чтобы загружать разные спрайты без изменения кода сцены. 2. **Старт уровня с параметрами:** Передайте идентификатор уровня, сложность, здоровье игрока или снаряжение.

game.scene.start('LevelScene', { levelId: 5, difficulty: 'hard', playerHealth: 80 });

3. **Возврат в меню с результатом:** После завершения уровня сцена результатов может получить объект с итоговым счётом и потраченным временем, чтобы отобразить статистику.

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

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

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