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

При создании браузерных игр важно оптимизировать загрузку ресурсов, чтобы игрок не ушел, пока ждет скачивания контента. Загрузка аудио в потоковом режиме (streaming) позволяет начать воспроизведение музыки и звуков до того, как файл будет полностью загружен. Это критически важно для больших аудиодорожек, которые иначе блокировали бы загрузку уровня. В этой статье мы разберем пример из официальной документации Phaser и покажем, как с помощью флага `stream: true` загружать аудиофайлы фоном, не прерывая игровой процесс.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    text;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.text = this.add.text(10, 10, 'Loading audio ...', { font: '16px Courier', fill: '#00ff00' });

        this.load.audio('dafunk', [
            'assets/audio/Dafunk - Hardcore Power (We Believe In Goa - Remix).ogg',
            'assets/audio/Dafunk - Hardcore Power (We Believe In Goa - Remix).mp3',
            'assets/audio/Dafunk - Hardcore Power (We Believe In Goa - Remix).m4a'
        ], { stream: true });
    }

    create ()
    {
        this.sound.pauseOnBlur = false;

        const music = this.sound.add('dafunk');

        music.play();

        this.text.setText('Playing Dafunk - Hardcore Power (We Believe In Goa - Remix)');
    }
}

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

const game = new Phaser.Game(config);

Зачем нужен потоковый режим загрузки аудио

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

Потоковая загрузка (stream: true) решает эту проблему. Браузер начинает скачивать файл и может запустить воспроизведение, как только загрузится достаточно данных для буферизации. Это похоже на то, как работают стриминговые сервисы вроде YouTube или Spotify.

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

Настройка загрузчика и объявление аудиоресурса

Вся конфигурация происходит в методе preload() сцены. Сначала задается базовый URL для загрузки ресурсов, что удобно, если все файлы лежат в одной директории. Затем создается текстовый объект для отображения статуса загрузки.

Основная магия происходит в вызове this.load.audio(). Обратите внимание на три ключевых момента: 1. Массив путей к файлам в разных форматах — это обеспечивает кроссбраузерную совместимость. 2. Объект конфигурации с единственным свойством stream: true.

class Example extends Phaser.Scene
{
    text;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.text = this.add.text(10, 10, 'Loading audio ...', { font: '16px Courier', fill: '#00ff00' });

        this.load.audio('dafunk', [
            'assets/audio/Dafunk - Hardcore Power (We Believe In Goa - Remix).ogg',
            'assets/audio/Dafunk - Hardcore Power (We Believe In Goa - Remix).mp3',
            'assets/audio/Dafunk - Hardcore Power (We Believe In Goa - Remix).m4a'
        ], { stream: true });
    }

Воспроизведение и важная настройка `pauseOnBlur`

Когда ресурс загружен (даже частично), в методе create() мы можем начать его воспроизведение. Однако есть нюанс: по умолчанию Phaser приостанавливает звук, когда игрок переключается на другую вкладку браузера (pauseOnBlur = true). Для фоновой музыки это часто нежелательно.

Поэтому первой же строчкой мы отключаем это поведение, устанавливая this.sound.pauseOnBlur = false. Теперь музыка будет играть, даже если окно игры не в фокусе.

Далее создается звуковой объект с ключом 'dafunk' и сразу запускается методом .play(). Обновление текста на экране подтверждает, что воспроизведение началось.

create ()
    {
        this.sound.pauseOnBlur = false;

        const music = this.sound.add('dafunk');

        music.play();

        this.text.setText('Playing Dafunk - Hardcore Power (We Believe In Goa - Remix)');
    }
}

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

Код завершается стандартной конфигурацией игры Phaser. Мы указываем автоматический выбор рендерера (Phaser.AUTO), размеры холста и родительский контейнер. Самое важное — передаем в конфиг наш класс сцены Example.

Создание экземпляра new Phaser.Game(config) запускает весь описанный выше цикл: preload, create, update.

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

const game = new Phaser.Game(config);

Практические советы и ограничения

Используйте потоковую загрузку для длинных аудиофайлов (музыка, диалоги, ambient). Для коротких звуков (выстрелы, клики) это излишне и может создать ненужную нагрузку.

Помните о кросбраузерности. Всегда предоставляйте несколько форматов (как в примере: OGG, MP3, M4A), так как разные браузеры поддерживают разные кодеки.

Важное ограничение: на некоторых мобильных браузерах автовоспроизведение аудио (music.play() без явного действия пользователя) может быть заблокировано. В продакшене стоит запускать первый звук по клику или касанию.

Для контроля над загруженным аудио объект, возвращаемый this.sound.add(), предоставляет методы pause(), stop(), setVolume() и другие.

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

Потоковая загрузка аудио в Phaser — мощный инструмент для создания плавного игрового опыта без задержек. Он позволяет играм с богатым звуковым сопровождением запускаться практически мгновенно. Для экспериментов попробуйте: 1. Загрузить один и тот же трек с флагом stream: true и без него, чтобы наглядно увидеть разницу во времени старта. 2. Связать прогресс загрузки аудио с индикатором на экране, используя события загрузчика Phaser. 3. Создать систему управления плейлистом, где треки загружаются потоково и переключаются без пауз.