О чем этот пример
Работа с множеством мелких звуковых эффектов может превратиться в хаос из-за отдельных файлов и большого количества запросов. Phaser предлагает элегантное решение — аудиоспрайты. Они объединяют множество коротких звуков в один файл, подобно спрайт-листам для графики. Это упрощает загрузку, управление и воспроизведение, особенно в играх с десятками эффектов. В этой статье мы разберем пример, который показывает, как загрузить аудиоспрайт и привязать каждую звуковую "спрайт" к интерактивной кнопке.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
/**
* @author Pavle Goloskokovic <pgoloskokovic@gmail.com> (http://prunegames.com)
*/
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('title', 'assets/pics/catastrophi.png');
this.load.spritesheet('button', 'assets/ui/flixel-button.png', { frameWidth: 80, frameHeight: 20 });
this.load.bitmapFont('nokia', 'assets/fonts/bitmap/nokia16black.png', 'assets/fonts/bitmap/nokia16black.xml');
this.load.audioSprite('sfx', 'assets/audio/SoundEffects/fx_mixdown.json', [
'assets/audio/SoundEffects/fx_mixdown.ogg',
'assets/audio/SoundEffects/fx_mixdown.mp3'
]);
}
create ()
{
this.add.image(400, 300, 'title');
const spritemap = this.cache.json.get('sfx').spritemap;
let i = 0;
for (let spriteName in spritemap)
{
if (!spritemap.hasOwnProperty(spriteName))
{
continue;
}
this.makeButton(spriteName, 680, 115 + i*40);
i++;
}
this.input.on('gameobjectover', function (pointer, button)
{
this.setButtonFrame(button, 0);
}, this);
this.input.on('gameobjectout', function (pointer, button)
{
this.setButtonFrame(button, 1);
}, this);
this.input.on('gameobjectdown', function (pointer, button)
{
this.sound.playAudioSprite('sfx', button.name);
this.setButtonFrame(button, 2);
}, this);
this.input.on('gameobjectup', function (pointer, button)
{
this.setButtonFrame(button, 0);
}, this);
}
makeButton(name, x, y)
{
const button = this.add.image(x, y, 'button', 1)
.setInteractive();
button.name = name;
button.setScale(2, 1.5);
const text = this.add.bitmapText(x - 40, y - 8, 'nokia', name, 16);
text.x += (button.width - text.width) / 2;
}
setButtonFrame(button, frame)
{
button.frame = button.scene.textures.getFrame('button', frame);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example,
pixelArt: true,
audio: {
disableWebAudio: true
}
};
const game = new Phaser.Game(config);
Что такое аудиоспрайт и как его загрузить
Аудиоспрайт — это один аудиофайл, содержащий множество коротких звуковых клипов, и JSON-файл с таймингом (временными метками) для каждого из них. Это позволяет загрузить все звуки эффектов одним запросом.
В методе preload() используется this.load.audioSprite(). Первый аргумент — ключ для кэша ('sfx'), второй — путь к JSON-файлу с разметкой, третий — массив путей к самим аудиофайлам в разных форматах для совместимости браузеров.
this.load.audioSprite('sfx', 'assets/audio/SoundEffects/fx_mixdown.json', [
'assets/audio/SoundEffects/fx_mixdown.ogg',
'assets/audio/SoundEffects/fx_mixdown.mp3'
]);
После загрузки данные о таймингах каждого звука (спрайте) сохраняются в кэше JSON под тем же ключом ('sfx'). Доступ к ним можно получить через this.cache.json.get('sfx').spritemap.
Создание интерфейса для воспроизведения
Чтобы дать игроку возможность проиграть каждый звук, пример динамически создает кнопки. Сначала из кэша извлекается объект spritemap, который содержит имена всех звуковых спрайтов как ключи.
const spritemap = this.cache.json.get('sfx').spritemap;
Затем в цикле for...in для каждого имени звука вызывается метод makeButton(). Важно использовать hasOwnProperty() для проверки, чтобы избежать итерации по унаследованным свойствам прототипа.
for (let spriteName in spritemap)
{
if (!spritemap.hasOwnProperty(spriteName))
{
continue;
}
this.makeButton(spriteName, 680, 115 + i*40);
i++;
}
Метод makeButton() создает интерактивное изображение кнопки и подписывает его битовым шрифтом. Ключевой момент — имя звукового спрайта (spriteName) присваивается свойству button.name. Это свойство позже будет использовано для идентификации, какой звук проигрывать.
button.name = name;
Обработка ввода и воспроизведение звука
Вся логика реакции на наведение и клик мыши по кнопкам настраивается через обработчики событий ввода (input.on). События gameobjectover, gameobjectout, gameobjectdown и gameobjectup отслеживают взаимодействие с любым игровым объектом.
Самый важный обработчик — для события gameobjectdown (кнопка мыши нажата над объектом). В нем происходит воспроизведение звука с помощью this.sound.playAudioSprite().
this.input.on('gameobjectdown', function (pointer, button)
{
this.sound.playAudioSprite('sfx', button.name);
this.setButtonFrame(button, 2);
}, this);
Первым аргументом передается ключ аудиоспрайта ('sfx'), а вторым — имя конкретного звукового спрайта, которое мы ранее сохранили в button.name. Phaser сам находит в JSON нужные временные метки и воспроизводит только этот фрагмент из общего аудиофайла.
Метод setButtonFrame() обновляет кадр спрайтшита кнопки, чтобы визуально отображать её состояние (обычная, наведение, нажатая).
Конфигурация проекта и важная настройка audio
Обратите внимание на конфигурацию игры, особенно на объект audio. В данном примере явно отключается WebAudio API.
const config = {
// ... другие настройки
audio: {
disableWebAudio: true
}
};
Это сделано потому, что аудиоспрайты в Phaser 3 корректно работают с HTML5 Audio API. Если вы планируете использовать аудиоспрайты, эта настройка может быть необходимой для гарантированной работы. Также включен режим pixelArt: true, который отключает сглаживание текстур, что важно для ретро-стилистики.
Что попробовать дальше
Аудиоспрайты — это мощный инструмент для оптимизации и организации звукового сопровождения в Phaser. Они сокращают количество HTTP-запросов и упрощают управление множеством эффектов через единый JSON-манифест. Для экспериментов попробуйте: создать свой аудиоспрайт из набора WAV-файлов с помощью инструментов вроде audiosprite; управлять громкостью или скоростью воспроизведения отдельных спрайтов через параметры метода playAudioSprite; или связать воспроизведение не с кликом, а с другими игровыми событиями, например, столкновением объектов.
