2013-02-28 142 views
6

我有以下的基于canvas的游戏的JS代码。通过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); 
} 

这工作,但它向服务器发送请求,每次被调用时,下载的声音文件。或者,如果我宣布了音频对象事先:

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

function createExplosion() { 
    snd.play(); 
} 

这工作,但是如果之前的声音播放完createExplosion函数被调用,它不播放声音都没有。这意味着一次只允许一次播放声音文件 - 在发生多次爆炸的情况下,它根本不起作用。

有什么方法可以正确播放多次与自身重叠的音频文件?

+1

结束了与使用AudioFX库去:HTTP:// codeincomplete .com/posts/2011/9/17/revisiting_html5_audio/ – 2013-02-28 03:25:00

回答

0

试试这个:

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

然后你第一次调用它,将取回的声音,但之后它会重复使用同一个声音对象每次。


编辑:您还可以重复预装允许播放声音不止一次在同一时间:

(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(); 
    }; 
})(); 

请注意,如果你玩的声音也与其自身重叠,这将发送多个请求很多,但它应该很快返回Not Modified,并且只有在您比以前多次播放时才会这样做。

+0

这会遭遇同样的问题。声音会播放,但在前一个实例播放完毕之前尝试播放会导致声音根本不播放。在播放音频对象之前,它似乎是一个问题。 – 2013-02-28 01:11:28

+0

我通常的解决方案是构建一个数组。我会用这个编辑我的答案。 – 2013-02-28 01:12:17

+0

似乎没有工作,但我对你想要做的事情有一个粗略的想法。 – 2013-02-28 01:27:47

0

我一直在寻找这个在我正在建设的俄罗斯方块游戏的年龄,我认为这个解决方案是最好的。

function playSoundMove() { 
    var sound = document.getElementById("move"); 
    sound.load();  
    sound.play(); 
} 

只是它已加载并准备好去。

1

您可以复制节点与cloneNode()play()复制节点。

我的声音元素看起来是这样的:

<audio id="knight-audio" src="knight.ogg" preload="auto"></audio> 

,我有一个onClick监听器做到了这一点:

function click() { 
    const origAudio = document.getElementById("knight-audio"); 
    const newAudio = origAudio.cloneNode() 
    newAudio.play() 
} 

而且,由于audio元素是不会被显示出来,你实际上并不需要将节点附加到任何东西上。

我验证了客户端和服务器端Chrome浏览器只尝试下载音频文件一次。

注意事项:我不确定关于性能的影响,因为在我的网站上这个片段播放的页面最多不会超过40倍。如果你做的比这个大得多,你可能不得不清理音频节点?

0

更多地依赖于内存比处理时间,我们可以使音频的多个克隆的数组,然后通过顺序播放它们:

function gameSnd(){ 
    this.t = new Audio('sounds/tick.wav'); 
    this.v = new Audio('sounds/victory.wav'); 
    this.c = 0; 
    this.ticks=[]; 
    for(var i = 0; i<10;i++) 
    this.ticks.push(this.t.cloneNode()); 

    this.tick = function(){ 
    this.c = (this.c + 1)%10; 
    this.ticks[this.c].play(); 
    } 

    this.victory = function(){ 
    this.v.play(); 
    } 

}