我有一个基于画布的游戏的以下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);
}
这样可行,但是每次调用时它都会发送一个服务器请求来下载声音文件。或者,如果我事先声明了Audio对象:
var snd = new Audio();
snd.src = EXPLOSION;
snd.volume = 0.5;
function createExplosion() {
snd.play();
}
这样可行,但是如果在声音播放完毕之前调用了createExplosion函数,它根本不播放声音。这意味着一次只允许声音文件的单个播放 - 并且在发生多次爆炸的情况下它根本不起作用。
有没有办法正确播放多次与自身重叠的音频文件?
答案 0 :(得分:3)
您只需复制具有重复节点的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倍。如果你做的事情要大得多,你可能需要清理音频节点吗?
答案 1 :(得分:1)
试试这个:
(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,并且只有在您播放的次数超过以前时才会这样做。
答案 2 :(得分:1)
我正在建造一个俄罗斯方块游戏中寻找这个年龄,我认为这个解决方案是最好的。
function playSoundMove() {
var sound = document.getElementById("move");
sound.load();
sound.play();
}
只需加载它就可以了。
答案 3 :(得分:0)
更多地依赖于内存而不是处理时间,我们可以创建一个包含音频的多个克隆的数组,然后按顺序播放它们:
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();
}
}
答案 4 :(得分:0)
在我的游戏中,我正在使用前置放大器,但在启动声音之后(根本不预加载或在页面加载时预加载所有内容并不聪明,某些声音根本无法在某些游戏中播放,为什么要加载它们)
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