通过JS重叠播放音频

Luc*_*ney 7 javascript audio html5 game-engine html5-canvas

我有一个基于画布的游戏的以下JS代码.

var EXPLOSION = "sounds/explosion.wav";

function playSound(str, vol) {
  var snd = new Audio();
  snd.src = str;
  snd.volume = vol;
  snd.play();
}

function createExplosion() {
  playSound(EXPLOSION, 0.5);
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,但每次调用时它都会发送一个服务器请求来下载声音文件.或者,如果我事先声明了Audio对象:

var snd = new Audio();
snd.src = EXPLOSION;
snd.volume = 0.5;

function createExplosion() {
  snd.play();
}
Run Code Online (Sandbox Code Playgroud)

这可行,但是如果在声音播放完毕之前调用createExplosion函数,它根本不播放声音.这意味着一次只允许声音文件的单个播放 - 并且在发生多次爆炸的情况下它根本不起作用.

有没有办法正确播放多次与自身重叠的音频文件?

Nie*_*sol 1

尝试这个:

(function() {
    var snds = {};
    window.playSound(str,vol) {
        if( !snds[str]) (snds[str] = new Audio()).src = str;
        snds[str].volume = vol;
        snds[str].play();
    }
})();
Run Code Online (Sandbox Code Playgroud)

然后,第一次调用它时,它会获取声音,但此后每次调用它时,它都会重用相同的声音对象。


编辑:您还可以预加载重复项,以允许声音一次播放多次:

(function() {
    var snds = {}
    window.playSound = function(str,vol) {
        if( !snds[str]) {
            snds[str] = [new Audio()];
            snds[str][0].src = str;
        }
        var snd = snds[str], pointer = 0;
        while( snd[pointer].playing) {
            pointer++;
            if( pointer >= snd.length) {
                snd.push(new Audio());
                snd[pointer].src = str;
            }
        }
        snd[pointer].volume = vol;
        snd[pointer].play();
    };
})();
Run Code Online (Sandbox Code Playgroud)

请注意,如果您播放的声音重叠太多,这将发送多个请求,但它应该很快返回“未修改”,并且只有当您播放的次数比以前多时才会这样做。