javascripthtmlaudiohtml5-canvas

audio.play() without waiting for previous sound to end?


I'm coding a game and I have a rough draft of the shooting mechanism, but I want to have it play a sound, and sometimes it won't play because it already is, and no matter how short I make the sound, it still does this on some level. My code is below, any advice? I want to have it be able to play at any time regardless of the status of any previous executions of the audio.play() method, I tried putting the audio.play() method in a separate function and calling that function, but it did nothing.

var canvas = document.getElementById('imlonely');
var ctx = canvas.getContext('2d');
var crosshairs = {
x: 250,
y: 250,
r: 20,
s: 0,
e: Math.PI * 2 
} 
var lives = 5;
var audio = new Audio('https://freesound.org/people/RSilveira_88/sounds/216317/download/216317__rsilveira-88__gunshot-09.wav');
function soundGo(){
audio.play();  
}
var l1 = crosshairs.x - 20
var l2 = crosshairs.x + 20
var l3 = crosshairs.y - 20
var l4 = crosshairs.y + 20
var l5 = crosshairs.y;
var l6 = crosshairs.x
var e1 = {
x: 20,
y: 20,
w: 20,
h: 20
}
var e2 = {
x: 20,
y: 20,
w: 20,
h: 20
}
function renderEnemy(){
ctx.fillRect(e1.x,e1.y,e1.w,e1.w);
if(e1.w<300){
e1.w = e1.w + e1.w/200;
}
ctx.fillRect(e2.x,e2.y,e2.w,e2.w);
if(e2.w<300){
e2.w = e1.w + e1.w/200;
}
else{
e1.w = 20;
generateEnemyOne(); 
lives--; 
}
}
function generateEnemyOne(){
e1.x = Math.floor(Math.random() * 500)
e1.y = Math.floor(Math.random() * 500)
}
generateEnemyOne()
function renderCrosshairs(){
  ctx.strokeStyle = 'crimson';
ctx.beginPath();
ctx.arc(crosshairs.x, crosshairs.y,crosshairs.r, crosshairs.s, crosshairs.e);
ctx.stroke();
ctx.moveTo(l1,l5);
ctx.lineTo(l2,l5);
ctx.stroke();
ctx.moveTo(l6,l3);
ctx.lineTo(l6,l4);
ctx.stroke();
l1 = crosshairs.x - 20
l2 = crosshairs.x + 20
 l3 = crosshairs.y - 20
 l4 = crosshairs.y + 20
 l5 = crosshairs.y;
l6 = crosshairs.x
}
function moveIt(event){
crosshairs.x = event.clientX;
crosshairs.y = event.clientY ;  
}




function draw(){
if (lives <= 0){
alert('game over');  
return;
}
  ctx.beginPath();
  ctx.clearRect(0,0,1000,1000)
renderEnemy();
renderCrosshairs();
setTimeout(draw,2)
}
draw();
function shoot(){
soundGo();
}
canvas.addEventListener("mousemove", moveIt);
canvas.addEventListener("mousedown", shoot);
<!DOCTYPE html>
<html>
  <canvas id = 'imlonely' width = '500' height = '500' style = 'border-style: solid;'> Sorry, there was a problem dispaying the canvas. Maybe your browser doesen't support the canvas element, maybe it's something else.</canvas>
    <script src="script.js"></script>
</html>


Solution

  • A single audio cannot be playing in multiple instances. The audio must finish before it can be played again.

    You must replace this code:

    var audio = new Audio('https://freesound.org/people/RSilveira_88/sounds/216317/download/216317__rsilveira-88__gunshot-09.wav');
    function soundGo(){
    audio.play();  
    }
    

    With this:

    // In each instance, a new audio is created.
    function soundGo(){
      var audio = new Audio('https://freesound.org/people/RSilveira_88/sounds/216317/download/216317__rsilveira-88__gunshot-09.wav');
      audio.play();  
    }
    

    If a new audio is locally created each time, it plays immediately.