О чем этот пример
Использование маркеров в аудиофайлах — это мощный способ организации звуковых эффектов в играх. Вместо загрузки десятков отдельных файлов вы можете хранить все эффекты в одном и воспроизводить нужные фрагменты по требованию. В этой статье мы разберем пример из официальной документации Phaser, который показывает, как загрузить один аудиофайл с несколькими эффектами и создавать кнопки для их воспроизведения. Этот подход экономит ресурсы, упрощает управление контентом и ускоряет загрузку игры.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
markers = [
{ name: 'alien death', start: 1, duration: 1.0, config: {} },
{ name: 'boss hit', start: 3, duration: 0.5, config: {} },
{ name: 'escape', start: 4, duration: 3.2, config: {} },
{ name: 'meow', start: 8, duration: 0.5, config: {} },
{ name: 'numkey', start: 9, duration: 0.1, config: {} },
{ name: 'ping', start: 10, duration: 1.0, config: {} },
{ name: 'death', start: 12, duration: 4.2, config: {} },
{ name: 'shot', start: 17, duration: 1.0, config: {} },
{ name: 'squit', start: 19, duration: 0.3, config: {} }
];
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.audio('sfx', [
'assets/audio/SoundEffects/fx_mixdown.ogg',
'assets/audio/SoundEffects/fx_mixdown.mp3'
]);
}
create ()
{
this.add.image(400, 300, 'title');
for (let i = 0; i < this.markers.length; i++)
{
this.makeButton.call(this, this.markers[i].name, i);
}
this.input.on('gameobjectover', (pointer, button) =>
{
this.setButtonFrame(button, 0);
});
this.input.on('gameobjectout', (pointer, button) =>
{
this.setButtonFrame(button, 1);
});
this.input.on('gameobjectdown', function (pointer, button)
{
const index = button.getData('index');
this.sound.play('sfx', this.markers[index]);
this.setButtonFrame(button, 2);
}, this);
this.input.on('gameobjectup', (pointer, button) =>
{
this.setButtonFrame(button, 0);
});
}
makeButton (name, index)
{
const button = this.add.image(680, 115 + index * 40, 'button', 1).setInteractive();
button.setData('index', index);
button.setScale(2, 1.5);
const text = this.add.bitmapText(button.x - 40, button.y - 8, 'nokia', name, 16);
text.x += (button.width - text.width) / 2;
}
setButtonFrame (button, frame)
{
button.frame = button.scene.textures.getFrame('button', frame);
}
}
/**
* @author Pavle Goloskokovic <pgoloskokovic@gmail.com> (http://prunegames.com)
*/
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example,
pixelArt: true
};
const game = new Phaser.Game(config);
Подготовка данных: массив маркеров
Вся логика работы со звуками начинается с определения маркеров. Маркер — это объект, который указывает на фрагмент внутри аудиофайла.
В классе сцены Example объявлен массив markers. Каждый маркер содержит имя (name), время начала в секундах (start), длительность (duration) и конфигурационный объект (config), который может содержать дополнительные параметры воспроизведения, такие как громкость или зацикливание.
markers = [
{ name: 'alien death', start: 1, duration: 1.0, config: {} },
{ name: 'boss hit', start: 3, duration: 0.5, config: {} },
// ... другие маркеры
];
Таким образом, в одном файле fx_mixdown мы храним девять различных звуковых эффектов, доступ к которым получаем по времени.
Загрузка ресурсов в preload
Метод preload() отвечает за загрузку всех необходимых ресурсов перед созданием сцены. Обратите внимание, что аудио загружается как единый файл с ключом 'sfx'. Phaser поддерживает загрузку нескольких форматов (OGG и MP3) для обеспечения кросс-браузерной совместимости.
this.load.audio('sfx', [
'assets/audio/SoundEffects/fx_mixdown.ogg',
'assets/audio/SoundEffects/fx_mixdown.mp3'
]);
Также загружаются изображение для фона, спрайтшит для кнопок и bitmap-шрифт для текста. Метод this.load.setBaseURL() устанавливает базовый URL, что позволяет указывать относительные пути для остальных ресурсов.
Создание интерактивных кнопок
В методе create() создается интерфейс. Для каждого маркера из массива вызывается метод makeButton(), который создает интерактивную кнопку.
for (let i = 0; i < this.markers.length; i++)
{
this.makeButton.call(this, this.markers[i].name, i);
}
Метод makeButton() создает изображение-кнопку из спрайтшита, делает его интерактивным с помощью setInteractive() и сохраняет индекс маркера в данных объекта через setData(). Рядом с кнопкой создается текст с именем эффекта.
const button = this.add.image(680, 115 + index * 40, 'button', 1).setInteractive();
button.setData('index', index);
Важно, что в спрайтшите button три кадра: 0 — наведение, 1 — обычное состояние, 2 — нажатие. Это используется для визуальной обратной связи.
Обработка событий ввода и воспроизведение звука
Ядро функциональности — обработка событий мыши. Сцена слушает события gameobjectover, gameobjectout, gameobjectdown и gameobjectup. При нажатии на кнопку (gameobjectdown) извлекается сохраненный индекс и воспроизводится звук.
Ключевая строка — вызов this.sound.play() с передачей ключа аудио и объекта маркера.
this.sound.play('sfx', this.markers[index]);
Phaser Audio Manager использует переданный маркер, чтобы воспроизвести только указанный сегмент основного аудиофайла. Метод setButtonFrame() меняет кадр спрайта кнопки, обеспечивая визуальную реакцию на действия игрока.
Конфигурация игры и запуск
Пример завершается стандартной для Phaser 3 конфигурацией игры. Обратите внимание на параметр pixelArt: true, который включает сглаживание для пиксельной графики, что важно для сохранения четкости спрайтов кнопок и шрифта.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example,
pixelArt: true
};
const game = new Phaser.Game(config);
Этот объект конфигурации передается в конструктор Phaser.Game, который инициализирует и запускает игровой цикл.
Что попробовать дальше
Использование аудиомаркеров в Phaser — это эффективный и профессиональный подход к управлению звуками в вашей игре. Он позволяет уменьшить количество HTTP-запросов и упростить логику работы со звуковыми эффектами. Для экспериментов попробуйте: добавить в конфиг маркеров параметры volume или loop; создать систему случайного выбора вариаций звука внутри одного маркера; или реализовать остановку звука по повторному нажатию на кнопку.
