Файл: Беляев С А - Разработка игр на языке JavaScript - 2016.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Программирование

Добавлен: 25.10.2018

Просмотров: 7585

Скачиваний: 136

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Управление звуком

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. Если


background image

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, // àóäèîêîíòåêñò


background image

Управление звуком

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); // ïîäêëþ÷åíèå

// ê äèíàìèêàì

}


background image

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;


background image

Управление звуком

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.