Файл: Беляев С А - Разработка игр на языке JavaScript - 2016.pdf
Добавлен: 25.10.2018
Просмотров: 7585
Скачиваний: 136
Управление звуком
111
function loadSound(url) {
var request = new XMLHttpRequest();
// ñîçäàíèå àñèíõðîííîãî çàïðîñà
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// òèï ðåçóëüòàòà - áàéòû
request.onload = function () {
context.decodeAudioData(request.response,
function (buffer) {
playSound(buffer); // ïîëó÷åííûé ïîòîê
// áàéò - îçâó÷èòü
});
};
request.send();
}
function playSound(buffer) {
var sound = context.createBufferSource();
// Ñîçäàåòñÿ èñòî÷íèê çâóêà
sound.buffer = buffer; // íàñòðàèâàåòñÿ áóôåð
sound.connect(gainNode); // ïîäêëþ÷åíèå èñòî÷íèêà
// ê "êîëîíêàì"
sound.loop = false; // ïîâòîðÿòü
gainNode.gain.value = 0.2; // ãðîìêîñòü çâóêà
sound.start(0); // ïðîèãðûâàíèå çâóêà
}
loadSound("effects/boom.wav"); // çàãðóçêà çâóêà
</script>
</body>
</html>
Приведенный программный код несущественно отли
чается от примера «Проигрывание аудиофайлов». Рас
смотрим отличия.
var gainNode = context.createGain ? context.createGain() :
context.createGainNode();
Конструкция JavaScript «A ? B : C» проверяет усло
вие A, если оно верно, то выполняет B, иначе выполня
ет C. В данном фрагменте проверяется наличие функции
createGain аудиоконтекста, однако эта функция может
отсутствовать в предыдущих версиях Web Audio API. Если
112
Глава 7
она существует, то происходит ее вызов, если нет, то вы
зывается функция createGainNode. В результате создает
ся объект, который может управлять громкостью звука,
сохраняем его в gainNode.
gainNode.connect(context.destination);
Подключаем gainNode к динамикам.
Функция loadSound не претерпела изменений по срав
нению с программным кодом «Проигрывание аудиофай
лов». В функции playSound первые две строки остались
без изменений — создание источника звука и настройка
buffer.
sound.connect(gainNode);
Подключаем звук (sound) к gainNode.
sound.loop = false;
При использовании gainNode есть возможность зацик
ливать звук (loop). В данном случае звук будет проигры
ваться только один раз. При присваивании true звук бу
дет проигрываться непрерывно.
gainNode.gain.value = 0.2;
Данная конструкция позволяет установить громкость
звука. Предполагается число от 0 (нет звука) до 1 (100%
звука), но программа может принимать числа больше 1.
sound.start(0);
Запускается немедленное проигрывание аудиофайла.
При этом громкость составит 20% от максимальной гром
кости.
7.2.
МЕНЕДЖЕР ЗВУКА
Для управления звуком в игре целесообразно создать
менеджер звука (soundManager), который загрузит все
звуки, будет их хранить и проигрывать по мере необходи
мости.
var soundManager = {
clips: {}, // çâóêîâûå ýôôåêòû
context: null, // àóäèîêîíòåêñò
Управление звуком
113
gainNode: null, // ãëàâíûé óçåë
loaded: false, // âñå çâóêè çàãðóæåíû
init: function () { }, // èíèöèàëèçàöèÿ ìåíåäæåðà çâóêà
load: function (path, callback) { }, // çàãðóçêà îäíîãî àóäèîôàéëà
loadArray: function (array) { }, // çàãðóçèòü ìàññèâ çâóêîâ
play: function (path, settings) { }, // ïðîèãðûâàíèå ôàéëà
};
Аналогичный подход и методы по созданию менедже
ра звука представлены в [9], [10]. Многоточием в приве
денном фрагменте заменен код JavaScript, который будет
рассмотрен ниже.
clips: {}
Поле clips предназначено для хранения всех аудиофай
лов по именам. В качестве ключа поиска будет выступать
имя файла.
context: null
Аудиоконтекст хранится в поле context, при создании
менеджера контекст пустой.
gainNode: null
Поле gainNode предназначено для хранения объекта,
обеспечивающего управлением громкостью звука.
loaded: false
Поле loaded предназначено для хранения информации
об окончании загрузки всех звуков.
Функция init предназначена для инициализации ме
неджера звуков, функция load обеспечит загрузку одного
аудиофайла, а функция play — проигрывание аудиофай
ла. Обычно в игре требуется загрузка множества аудио
файлов, поэтому удобно для загрузки создать специаль
ную функцию loadArray.
function init() { // èíèöèàëèçàöèÿ ìåíåäæåðà çâóêà
this.context = new AudioContext();
this.gainNode = this.context.createGain ?
this.context.createGain() : this.context.createGainNode();
this.gainNode.connect(this.context.destination); // ïîäêëþ÷åíèå
// ê äèíàìèêàì
}
114
Глава 7
Инициализация менеджера звука обеспечивает на
стройку полей context и gainNode, как это выполнялось в
параграфе 7.1. Отличие заключается в том, что результат
хранится в виде полей менеджера звука (soundManager).
function load(path, callback) {
if (this.clips[path]) { // ïðîâåðÿåì, ÷òî óæå çàãðóæåíû
callback(this.clips[path]); // âûçûâàåì çàãðóæåííûé
return; // âûõîä
}
var clip = {path: path, buffer: null, loaded: false}; // êëèï, áóôåð,
// çàãðóæåí
clip.play = function (volume, loop) {
soundManager.play(this.path, {looping: loop?loop:false,
volume: volume?volume:1});
};
this.clips[path] = clip; // ïîìåùàåì â "ìàññèâ" (ëèòåðàë)
var request = new XMLHttpRequest();
request.open('GET', path, true);
request.responseType = 'arraybuffer';
request.onload = function () {
soundManager.context.decodeAudioData(request.response,
function (buffer) {
clip.buffer = buffer;
clip.loaded = true;
callback(clip);
});
};
request.send();
}
Функция load принимает два параметра: путь до за
гружаемого аудиофайла (path) и функцию, которая дол
жна быть вызвана в результате успешной загрузки файла
(callback).
if (this.clips[path])
Проверяется, что клип (аудиофайл) path уже загру
жен. Если условие верно, то выполняются два действия:
callback(this.clips[path]);
return;
Управление звуком
115
Первым действием вызывается функция callback, ко
торой в качестве параметра передается загруженный файл.
Вторым действием осуществляется выход из функции load.
var clip = {path: path, buffer: null, loaded: false};
Создается новый объект (клип), который будет хранить
информацию о загруженном аудиофайле. В нем в качестве
полей помещаются путь до аудиофайла, buffer для хране
ния потока байт и признак загрузки аудиофайла в брау
зер пользователя (loaded).
clip.play = function (volume, loop) {
soundManager.play(this.path, {looping: loop?loop:false,
volume: volume?volume:1});
};
В поле play клипа сохраняется функция для проигры
вания аудиофайла. Она принимает два параметра: гром
кость (volume) и признак зацикленности (loop). Функция
выполняет единственное действие — вызывает play менед
жера звука, которому в качестве параметров передает путь
до аудиофайла и новый объект со следующими признака
ми: зацикленный (looping) и громкость (volume). Значе
ния по умолчанию, если параметры в функцию не переда
ны: проиграть один раз на 100% громкости.
this.clips[path] = clip;
Созданный клип помещается в массив клипов. В каче
стве ключа используется путь до аудиофайла.
В следующих нескольких строках создается и исполь
зуется асинхронный запрос (request), идентичный запро
сам параграфа 7.1. Отличие составляет функция, которая
будет выполнена по окончании запроса.
function (buffer) {
clip.buffer = buffer;
clip.loaded = true;
callback(clip);
}
В объект clip сохраняется загруженный поток байт
(buffer), устанавливается признак того, что клип загру
жен (loaded) и вызывается функция callback.