Gunfire Semi Auto and Auto

Anyone know how to implement gunfire on left mouse pointer down? I was able to implement semi auto (one shot per click) but I could not find a good method for doing full auto while holding down on left mouse pointer. For full auto I attempted to do something like this:

let gunMagazineSize: number = 30;
let shoot: boolean

// mouse clicked down on  scene
scene.onPointerDown = (event) => { 

    // specifically left mouse clicked
    if (event.button == 0) {
         
        // initialize shoot
        shoot = true;
   
        // make gun sound 30 times with a growing offset
        for (let i = 0; gunMagazineSize < gun; i++) {
             if (shoot)
                setTimeout(() => this.gunSound.play(), 75*i);
            else
                break;      
    }
};

This will play a loop of a single shot sound 30 times in a row with a growing offset (75ms * i) when the mouse is down. I then tried to “kill” the sound by setting a shoot flag within the:

scene.onPointerUp = (event) => {
  if (event.button == 0)
    shoot = false;
}

I think the logic works when i do some console.log() debugging. However, I think the shoot flag is not getting updated within the scope of the loop so it never breaks the loop.

Anyways if anyone could help me that would be great :slight_smile: even if it means a complete throw away of my code since it might not even be close to proper implementation. Pretty new to BabylonJS FYI so maybe there is some implementation I am unaware of!

1 Like

It seems like a solid approach to me! I don’t fully understand the sound offset, but the general idea of setting a boolean between mouse down and mouse up is a perfectly reasonable approach!

sorry…not too helpful, but it’s definitely a route I would try myself!

I actually think i have a solve. In the code above the loop runs “instantaneously” and then the sound code trails after. So that is why my if statement doest get fired off as expected. So I found a stack overflow for how to create a delayed loop so my if statement can actually have time to check if it should play the sound or not. if it ends up working I will update here.

1 Like

Again, not too sure I fully understand the sound delay piece, but there are observables in Babylon that you can also look into.

It would be like flagging when a sound is done playing. Again, not sure if that applies, but something to look into.

1 Like

Got it working. Used a recursive delayed loop. End result is a weapon that fires one gunshot sound per left click or it will fire as long as the left click is held (up to 30 rounds)…producing an automatic sound. The gunshot sound is a .mp3 of a single shot btw. Wish I could demo for you but it functions like a “Call of Duty” m4 carbine sound basically :slight_smile:

    let shoot = true;

    // Returns a Promise that resolves after "ms" Milliseconds
    const timer = ms => new Promise(res => setTimeout(res, ms))

    let load = async () => { // We need to wrap the loop into an async function for this to work
      for (var i = 0; i < 30; i++) {
        if (shoot) this.gunSound.play()
        else break;
        console.log(i);
        await timer(75); // then the created Promise can be awaited
      }
    }

    load();

    scene.onPointerUp = (event) => {
      if (event.button == 0)
        shoot = false;
    }
2 Likes