Взаимодействие между активными сценами

Phaser предоставляет мощную систему для работы с множественными сценами, позволяя создавать сложные игровые архитектуры с разделением логики, интерфейса и фоновых процессов. Каждая сцена в Phaser — это самостоятельный объект с собственным жизненным циклом, набором игровых объектов и обработчиков событий. Управление сценами осуществляется через Scene Manager, доступный через this.scene внутри любой сцены.

Основные методы управления сценами:

  • this.scene.start(key, data) — останавливает текущую сцену и запускает указанную сцену key. Параметр data позволяет передать объект с данными.
  • this.scene.launch(key, data) — запускает сцену поверх текущей, не останавливая её. Часто используется для интерфейсных слоёв, таких как HUD или меню.
  • this.scene.stop(key) — останавливает указанную сцену.
  • this.scene.pause(key) / this.scene.resume(key) — приостанавливает и возобновляет выполнение сцены, сохраняя её состояние.
  • this.scene.switch(key) — сочетает остановку текущей сцены и запуск другой, аналогично start, но оставляет объекты памяти сцены для возможного повторного использования.

Передача данных между сценами

Передача информации между сценами возможна через параметры запуска или глобальные объекты состояния.

Параметры запуска сцены

При использовании scene.start или scene.launch можно передать объект data:

this.scene.start('GameScene', { score: 100, playerName: 'Alice' });

В целевой сцене доступ к данным осуществляется через метод init:

class GameScene extends Phaser.Scene {
    init(data) {
        this.score = data.score;
        this.playerName = data.playerName;
    }
}

Метод init вызывается до создания объектов сцены, что позволяет использовать данные для начальной настройки.

Глобальные объекты состояния

Для сложных проектов удобно использовать объект-синглтон, доступный из всех сцен:

window.gameState = {
    score: 0,
    level: 1,
    inventory: []
};

Из любой сцены можно изменять и читать данные:

window.gameState.score += 10;

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

Взаимодействие между сценами через события

Phaser предоставляет систему событий, которая облегчает коммуникацию между сценами. Основной инструмент — Event Emitter, встроенный в Scene и Game объекты.

Пример отправки события из одной сцены:

this.scene.get('UIScene').events.emit('updateScore', this.score);

В сцене-получателе:

class UIScene extends Phaser.Scene {
    create() {
        this.events.on('updateScore', (score) => {
            this.scoreText.setText(`Score: ${score}`);
        });
    }
}

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

Использование слоёв интерфейса и фонов

Сцены можно комбинировать по принципу слоёв. Например:

  • Основная сцена: GameScene с логикой игры.
  • Интерфейсная сцена: UIScene с элементами HUD.
  • Фоновая сцена: BackgroundScene с анимацией или партиклами.

Для запуска нескольких сцен одновременно используют launch:

this.scene.launch('UIScene');
this.scene.launch('BackgroundScene');

Каждая сцена обновляется независимо, но можно синхронизировать состояния через события или глобальные данные.

Совместное использование ресурсов

Phaser поддерживает один общий пул ресурсов (this.load), доступный из всех сцен. Это позволяет загружать текстуры, аудио и шрифты в Preloader Scene и использовать их в других сценах без повторной загрузки:

class PreloaderScene extends Phaser.Scene {
    preload() {
        this.load.image('player', 'assets/player.png');
        this.load.audio('bgMusic', 'assets/music.mp3');
    }
    create() {
        this.scene.start('GameScene');
    }
}

В GameScene достаточно обратиться к ресурсам по ключу:

this.add.sprite(100, 100, 'player');
this.sound.play('bgMusic');

Организация сложных взаимодействий

В крупных проектах сцены могут взаимодействовать по цепочке:

  1. Передача начальных данных через init для настройки уровня.
  2. Обновление состояния через глобальные объекты при изменении прогресса.
  3. События для мгновенного взаимодействия, например, изменение HUD при сборе предметов.
  4. Контроль порядка выполнения сцен через методы pause, resume и switch.

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

Практический пример интеграции сцен

// Основная игровая сцена
class GameScene extends Phaser.Scene {
    create() {
        this.score = 0;
        this.scene.launch('UIScene');
        this.events.on('collectItem', () => {
            this.score += 10;
            this.scene.get('UIScene').events.emit('updateScore', this.score);
        });
    }
}

// Сцена интерфейса
class UIScene extends Phaser.Scene {
    create() {
        this.scoreText = this.add.text(10, 10, 'Score: 0', { fontSize: '20px', fill: '#fff' });
        this.events.on('updateScore', (score) => {
            this.scoreText.setText(`Score: ${score}`);
        });
    }
}

// Инициализация игры
const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    scene: [PreloaderScene, GameScene, UIScene]
};
const game = new Phaser.Game(config);

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