О чем этот пример
При работе с зацикленной музыкой или звуками в Phaser можно столкнуться с неочевидным поведением: после первого проигрывания трек может замолчать. Эта проблема часто возникает из-за внутреннего кэширования аудиофайлов и может испортить впечатление от игры. Данная статья разбирает конкретный пример, объясняет причину сбоя и показывает, как правильно инициализировать и воспроизводить зацикленную музыку, чтобы избежать неожиданных пауз.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.audio('theme', [
'assets/audio/kyobi/wavs/nextLevel.wav'
]);
}
create ()
{
this.add.text(32, 32, 'Click to start music', { fill: '#ffffff' });
this.sound.pauseOnBlur = false;
this.input.once('pointerdown', () => {
const music = this.sound.add('theme');
music.play({ loop: true });
this.add.text(32, 64, '5 seconds until loop', { fill: '#ffffff' });
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Суть проблемы в примере
В предоставленном исходном коде есть скрытая проблема с воспроизведением зацикленного звука. На первый взгляд, всё логично: в preload загружается аудиофайл, а по клику он создается, проигрывается и ставится на повтор.
Однако, если запустить этот пример и подождать, может оказаться, что после завершения первого проигрывания трек не начнется заново, а просто остановится. Это поведение не соответствует ожидаемому от параметра loop: true.
Причина кроется в том, как Phaser управляет внутренними аудиоконтекстами и кэшем. Если аудио не было «подготовлено» к воспроизведению заранее, система может некорректно обработать запрос на повтор.
Правильная инициализация звука
Ключевое решение — создать звуковой объект (Sound) заранее, в методе create, а не в обработчике клика. Это позволяет Phaser полностью инициализировать аудио и правильно обработать флаг зацикливания.
Вот исправленная часть метода create. Обратите внимание, что мы создаем объект music сразу, но не запускаем его.
create ()
{
this.add.text(32, 32, 'Щелкните, чтобы начать музыку', { fill: '#ffffff' });
this.sound.pauseOnBlur = false;
// Звук создается ЗАРАНЕЕ, здесь
const music = this.sound.add('theme');
this.input.once('pointerdown', () => {
// А запускается уже по клику
music.play({ loop: true });
this.add.text(32, 64, '5 секунд до проверки цикла', { fill: '#ffffff' });
});
}
Этот подход гарантирует, что все внутренние связи аудиосистемы установлены до начала воспроизведения, и цикл будет работать корректно.
Конфигурация игры и настройка сцены
Основа примера — стандартная конфигурация игры и класс сцены. Важным моментом является настройка this.sound.pauseOnBlur = false. Она предотвращает автоматическую паузу в воспроизведении звука, когда пользователь переключается на другую вкладку браузера.
Полная конфигурация игры выглядит так:
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Класс сцены Example наследуется от Phaser.Scene и содержит два обязательных метода: preload для загрузки ресурсов и create для их инициализации.
Загрузка аудиоресурсов
Все необходимые для сцены ресурсы загружаются в методе preload. В данном примере загружается один аудиофайл.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.audio('theme', [
'assets/audio/kyobi/wavs/nextLevel.wav'
]);
}
Метод this.load.audio принимает два аргумента: ключ аудио ('theme'), по которому к нему можно будет обращаться, и массив путей к файлам. Phaser автоматически выберет подходящий формат (WAV, MP3, OGG) в зависимости от браузера. Указание базового URL через setBaseURL позволяет использовать относительные пути.
Что попробовать дальше
Основной вывод — для корректной работы зацикленных звуков в Phaser их объекты следует создавать на этапе инициализации сцены (create), а не откладывать создание до момента первого воспроизведения. Это позволяет аудиосистеме движка правильно «разогреться» и обрабатывать циклы. Для экспериментов попробуйте:
1. Запускать звук с задержкой через this.time.delayedCall.
2. Добавить несколько звуков с разными ключами и переключать их.
3. Управлять громкостью зацикленного трека в реальном времени через свойство volume объекта music.
