当前位置:嗨网首页>书籍在线阅读

37-使用Web Audio API开发太空掠夺者

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

7.7.2 使用Web Audio API开发太空掠夺者

接下来将使用Web Audio API开发新版的太空掠夺者。首先我们需要获取一个AudioContext对象。不过在写作本书时,仅有Chrome支持该接口,因此需要使用webkitAudioContext来代替AudioContext(尽管理论上Safari也支持该接口,但测试发现并不可行)。

var audioContext = new webkitAudioContext();

生成一对用于存储音频缓存的变量(射击和爆炸)。

var shootSoundBuffer;
var explodeSoundBuffer;

接着加载声音。为了让代码更加简明,创建一个函数用于加载音频。该函数仅接收一个名为url的参数,该参数则代表了声音文件的位置和文件名。在函数initApp()中,先获取audioType的值,然后再调用两个新的函数加载声音。

audioType = supportedAudioFormat(tempSound);
loadExplodeSound("explode1." + audioType);
loadShootSound("shoot1."+ audioType);

下一步,创建加载声音的两个函数。首先,需要创建XMLHttpRequest()的一个实例,并设置responseType为arraybuffer,将其配置为二进制数据。XMLHttpRequest()新实现的数据加载方式允许加载二进制文件,如音频文件。

然后,通过设置内嵌匿名函数作为onload的回调函数,为已加载的音频创建一个缓冲区。在这个函数中,通过调用audioContext. decodeAudioData()函数将二进制文件加载到制定的音频缓存区中。

该方法共有以下3个参数:

(1)音频数据(生成一个XMLHttpRequest,并调用request.response获取);

(2)成功回调函数(一个内嵌匿名函数,后面将会介绍);

(3)失败回调函数,名为onSoundError()。

成功回调函数仅有一个参数,该参数为包含音频数据的缓冲区。将该缓冲区的值传递给shootSoundBuffer,就可以在游戏中通过调用shootSoundBuffer播放该声音。然后调用itemLoaded()函数,修改太空掠夺者游戏中loadCount变量的值。

function loadShootSound(url) {
      var request = new XMLHttpRequest();
      request.open('GET', url, true);
      request.responseType = 'arraybuffer';
      request.onload = function() {
         audioContext.decodeAudioData(
         request.response, 
         function(buffer) {
         shootSoundBuffer = buffer;
         itemLoaded();
         }, onSoundError);
    };
   request.send();
  }
function onSoundError(e) {
  alert("error loading sound")
}

接着为爆炸声创建类似的函数,唯一的区别是在成功回调函数里将缓冲区的值传递给explodeSoundBuffer。

explodeSoundBuffer = buffer;

至此,在游戏中将音频的缓冲变量传递给函数playSound(),就可以播放音频。

playSound(shootSoundBuffer);

由于不需要管理声音的众多复本,因此现在的playSound()函数和之前的函数已经完全不同。在该函数中,首先通过调用audioContext.createBufferSource()获取到AudioBufferSourceNode的实例,并将它保存到变量source中。这个对象中保存着即将播放的声音。接着,将此函数中传入的缓冲区对象赋值给source的buffer属性。这个缓冲区对象表示内存中的一个声音数据(射击声或爆炸声)。

然后,通过调用audioContext.connect()函数为音频设置播放器(在这就使用默认的播放器,即电脑的扬声器)。最后调用函数source.noteOn(),并传入参数0(0标志着立即播放)。

由于AudioBufferSourceNode实例的函数noteOn()仅在第一次调用时有效,因此无须保存该source实例。当再次需要播放音频时,则再次产生一个实例。此外,音频播放完毕,浏览器会自动收集并释放该引用。

function playSound(soundBuffer) {
  var source = audioContext.createBufferSource();
  source.buffer = soundBuffer;
  source.connect(audioContext.destination);
  source.noteOn(0);
}

最后,为游戏添加自动射击功能。在此需添加两个变量:shootWaitFrames代表已等待时长,shootWait代表射击间隔。

var shootWaitedFrames = 8;
var shootWait = 8;

然后,在函数drawScreen()中添加以下代码来实现这个功能。

shootWaitedFrames++;
if (shootWaitedFrames > shootWait) {
     shoot();
     shootWaitedFrames = 0;;
}

通过计算函数drawScreen()的调用次数,当次数达到8次时,游戏会自动射击一发子弹。另外,可以通过修改shootWait的值来加快或减慢射击的速度。此外,还可以通过减小该值让声音更加频繁的出现,以此来达到测试Web Audio API的目的。

提示

在本书出版时,Chrome是唯一支持本例子的浏览器。另外,函数noteOn()将很快被函数start()取代。

读者可以运行本书代码包中的CH7EX10.html来体验新版的太空掠夺者。不过,在使用时还有一些需要注意的地方。

(1)需要在一个Web服务器上部署该例子,否则方法XMLHttpRequest()可能无法正常工作。

(2)如果不能正确加载音频,就需要在服务器的配置里上添加MIME类型。

正如读者所看到的,Web Audio API提供了一套在Canvas应用程序中高效播放声音的架构。利用Web Audio API可以实现很多功能,如添加过滤器以及获取音频数据进行可视化的音频处理等。在太空掠夺者的开发中,我们仅仅使用了该接口非常简单的功能。由于Web Audio API仍处於不断变化中,因此,查看W3C技术规范是了解和学习这项新技术的最好方法。