Javascript 通过重叠的JS播放音频

Javascript 通过重叠的JS播放音频,javascript,html,audio,html5-canvas,game-engine,Javascript,Html,Audio,Html5 Canvas,Game Engine,我有一个基于画布的游戏的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); } 这是可行的,但是每次调用声音文件时,它都会

我有一个基于画布的游戏的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函数,则它根本不会播放声音。这意味着一次只允许播放一次声音文件,在发生多次爆炸的场景中,它根本不起作用

有什么方法可以正确地播放音频文件多次重叠吗?

试试以下方法:

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

请注意,如果您播放的声音重叠过多,这将发送多个请求,但它应该不会很快返回修改,并且只有在您播放的次数比以前多的情况下才会这样做。

我在正在制作的俄罗斯方块游戏中一直在寻找这个解决方案,我认为这个解决方案是最好的

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

只需将其加载并准备就绪。

您可以使用该重复节点的
cloneNode()
play()
复制节点

我的音频元素如下所示:

<audio id="knight-audio" src="knight.ogg" preload="auto"></audio>
由于不显示
audio
元素,因此实际上不必将节点附加到任何内容

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


注意事项:我不确定对性能的影响,因为在我的网站上,一个页面最多播放不超过40倍。如果要执行比这更大的操作,您可能需要清理音频节点?

更多地依赖内存而不是处理时间,我们可以创建一个音频多克隆阵列,然后按顺序播放:

function gameSnd() {
    t = new Audio('sounds/tick.wav');
    v = new Audio('sounds/victory.wav');
    c = 0;
    ticks = [];

    for (var i = 0; i<10;i++)
        ticks.push(t.cloneNode());

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

    victory = function(){
        v.play();
    }
}
函数gameSnd(){
t=新音频('sounds/tick.wav');
v=新音频('sounds/victory.wav');
c=0;
滴答声=[];

对于(var i=0;i在我的游戏中,我使用预加载,但在声音启动后(完全不预加载或在页面加载时预加载所有内容并不明智,有些声音根本没有在某些游戏中播放,为什么要加载它们)

const audio{};
audio.dataload={'entity':false,'entityes':[],'n':0};
audio.dataload.ordernum=函数(){
audio.dataload.n=(audio.dataload.n+1)%10;
返回audio.dataload.n;
}
audio.dataload.play=函数(){
audio.dataload.entity=新音频('/some.mp3');

例如(设i=0;它也遇到同样的问题。声音将播放,但在前一个实例完成播放之前尝试再次播放会导致它根本不播放声音。播放()似乎有问题在音频对象完成之前对其进行预处理。我通常的解决方案是构建一个数组。我将使用该数组编辑我的答案。似乎不起作用,但我大致了解您试图执行的操作。仍然一次只获取一个声音-看起来它似乎只为每个声音字符串创建一个音频对象,尽管它应该创建更多的声音,因此我n使用AudioFX库也会遇到同样的问题:当需要响应时,WebAudioContext是一个好办法:你真的应该使用更好的变量名,而不仅仅是
t
c
v
,因为它们不给我任何线索。比如
victorySound
tickSound
>你好多了。
function gameSnd() {
    t = new Audio('sounds/tick.wav');
    v = new Audio('sounds/victory.wav');
    c = 0;
    ticks = [];

    for (var i = 0; i<10;i++)
        ticks.push(t.cloneNode());

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

    victory = function(){
        v.play();
    }
}
const audio {};
audio.dataload = {'entity':false,'entityes':[],'n':0};
audio.dataload.ordernum = function() {
  audio.dataload.n = (audio.dataload.n + 1)%10;
  return audio.dataload.n;
}
audio.dataload.play =  function() {
 
    audio.dataload.entity = new Audio('/some.mp3');
    for (let i = 0; i<10;i++) {
      audio.dataload.entityes.push(audio.dataload.entity.cloneNode());
    }
   
    audio.dataload.entityes[audio.dataload.ordernum()].play();
  
}

audio.dataload.play() // plays sound and preload sounds to memory when it isn't