top of page
Search
cedarcantab

Danmaku using Phaser 3 (step 4): Intermittent Bullets!

Updated: Oct 8, 2021

In all the examples up to now the Danmaku fired bullets at fixed intervals in an endless loop.

As a bit of variety how about if we had the Danmaku fire intermittently? For example, fire a round of 3 bullets rapidly fired at short fixed intervals, then a break, then another round of 3 bullets, etc.

I could do this using another manual counter like in the very original Danmaku. However, how about using Phaser's many timer events in some kind of combination?


In the previous 2 examples, we used the Phaser 2 timer event to call back the fireweapon() method at fixed intervals in an endless loop, i.e. a "looped timer", reproduced below for information below.

// create time event to call the fireweapon method at frequency determined by this.timeBetweenBullets
    this.machineGun = scene.time.addEvent({
      delay: this.timeBetweenBullets,
      callback: this.fireweapon,
      callbackScope: this,
      loop: true
    }); // end of timer event

Use of repeat timer

There is a variant of this called a "repeat timer" which calls back a particular function a prescribed number of times, which simply involves changing the "loop: true" to "repeat: n" which calls the callback function n+1 times (I don't know why it's n+1, as opposed to n). However, this timer, by definition, "dies" once it completes executing the prescribed function n+1 times. There is a method to reuse timer events. Hence, what if we created another timer event which executes the above repeat event, at fixed intervals? With a (quite) a bit of playing around I managed to get the result I want - the code (included in the constructor function of the extended Danmaku class) is reproduced below.

// create timer event to call the fireweapon method at frequency determined by this.timeBetweenBullets; ie fire one "round" of bullets
    const timerConfig = {
      delay: this.timeBetweenBullets,
      callback: this.fireweapon,
      callbackScope: this,
      repeat: this.bulletsInRound - 1 // repeat n+1 times
    };
    const machineGun = new Phaser.Time.TimerEvent(timerConfig); // end of timer event
    // create a timer event to fire rounds at frequency determined by this.timeBetweenRounds
    this.repeatWeaponFire = scene.time.addEvent({
      delay: this.timeBetweenRounds,
      callback: fireround,
      callbackScope: this,
      loop: true
    }); // end of timer event

    fireround(); // call fireround once immediately since the timer will wait before firing first round upon instantiation of this Danmaku class

    function fireround() {
      machineGun.reset(timerConfig); // seems reset of config of the timer event required after each time it is completed
      scene.time.addEvent(machineGun); // call the timer event that controls the firing of each round
    }

Reset timer? Closures? Scope?


The bit I struggled the most (and I don't know if this is an elegant way of doing this - please comment) is in bold. First, it took me a fair bit of time to realise that you need to reset the config of the machineGun timer otherwise it refuses to fire up after the first round. The other bit I am unsure about is declaring a function within the constructor function. If I declare the function (which is simply 2 lines of code) outside the constructor function, it refused to work. It is probably something to do with scopes and closures but I am not knowledgeable enough to understand whether there is a better way. Anyway, it seems to get the job done.


Tidying up


Other than the above, I made a few other changes which are of cosmetic nature

  • changed the bullet image to "bullet9"

  • set Danmaku angular velocity to zero (so bullets are fired in the same direction - straight down - all the time)

  • set bullet angular velocity to zero (bullet itself does not rotate)

  • added a bulletType as a parameter to the Danmaku class, so that you can specify bullet type when instantiating the Danmaku class, as opposed to setting it up in the bullets class

  • moved the enemy ship higher up the screen, so that we can see a few more "rounds"

Finally, I have changed the name of the extended Danmaku class as Intermittent. The previous examples built on each other, but I think I will keep this Danmaku class separate from those that fire continuously.


As always, the entire code in as a Codepen Pen is available below for your perusal.




Intermittent Bullets Danmaku using Phaser 3


Comments


記事: Blog2_Post
bottom of page