In lesson 4 I built a danmaku class that fired bullets on an intermittent basis. At that time, I had a basic danmaku object class and for each new type of danmaku pattern, building a sister class, including the intermittent danmaku. Since then I have taken a different approach and continued, in principle to build new patterns into one danmaku class. In this post, we will build the intermittent danmaku into the current version of the danmaku code. This will not be a long post since the basic mechanism to achieve the intermittent firing will be the same as lesson 4.
As a reminder, the basic mechanism is to have intermittent firing was to have 2 timer events: one timer event to fire a series of n shots, in whatever pattern, and a second timer which calls the first timer. The first timer, obviously repeats n-times, whereas the second timer is an infinite loop.
Key parameters
Before I get to the explanation of the code, I have, once again changed the names of some key variables, to hopefully make the code easier to understand, in light of what we are doing.
numberOfRounds --> numberOfShots: to be consistent with some other variables. Basically, by "shot" I am meaning bullet(s) fired in one go. For a 5 -way, a "shot" would be 5 bullets, and for a 5-way spread with 5 "rows", a "shot" would be 25 bullets
triggerRepeatFire --> startUpDanmaku: this is the function which must be called once after the danmaku is initiated, in order to get the timer(s) firing. It has been amended to include the set up of the second "outer" timer event.
repeatFireTimer --> repeatShotsTimer: this is the main timer which calls the fireShot function (which in turn calls the fireweapon function, which in turn calls the bullet.fire method)
repeatFireConfig --> repeatShotsConfig: this is the configuration parameter for the above timer
To achieve the intermittent firing, the following new parameters are created:
fireDanmaku: this is essentially the same as the original triggerRepeatFire function and resets/restarts the repeatShotsTimer (or for single shot, calls the fireShot function).
stopShotsTime; this is the interval time between the group of shots, in milli-seconds.
intervalTimer: this is the timer that calls the fireDanmaku, ie this is the "outer" timer event
intervalConfig: this is the configuration parameters for the above timer event.
Explanation of the various firing related functions and mechanism of intermittent danmaku
Instantiation of a a new danmaku. is instantiated by using new Danmaku(this, x, y, ...): at this point nothing happens, as the danamku has been created as an inactive/invisible Phaser object and it has not been "configured" with any danmaku patterns
Reset of danmaku: as a matter of course, the resetDanmaku method of the danmaku object is called after instantiation (and this is required when a pattern of an already firing danmaku is to be changed). this method clears out any existing tweens and timers.
Configuration of danmaku: the danmaku is configured using the setProperties(pattern) method. At this point, the danmaku has the timer(s) and tween(s) created, but they are not firing yet
Start the timers and tweens firing: startUpDanmaku is called. then the timers and tweens are started.
If the danmaku is a single shot (ie only 1 shot is fired - no repeat) then the fireShot function is called.
Otherwise, the timers are started. The timers in turn call the relevant bullet firing functions
The configuration of the 2 timers are key:
The "inner" timer event which calls the fireShot function (this is the timer event we have continued to rely on in past danmaku patterns).
// set up the timer event to call the fireShot function n number of times
this.repeatShotsConfig = {
delay: this.timeBetweenShots,
callback: this.fireShot,
callbackScope: this,
repeat: this.numberOfShots
};
if (this.numberOfShots !== 1) {
this.repeatShotsTimer = new Phaser.Time.TimerEvent(this.repeatShotsConfig);
}
And the "outer" timer event which calls the above timer. Note, how the delay is calculated.
// set up the "outer" timer event for intermittend danmaku
this.intervalConfig = {
delay: this.timeBetweenShots * this.numberOfShots + this.stopShotsTime,
callback: this.fireDanmaku,
args: [scene],
callbackScope: this,
repeat: -1
}
if (this.stopShotsTime) {
this.intervalTimer = new Phaser.Time.TimerEvent(this.intervalConfig);
}
I have mentioned in previous posts how I might call the "inner" timer event from the firing character object (eg the enemy object) create the outer timer event. However, I have decided to keep everything within the danmaku itself, at least for now.
Sample configuration
The pictured danmaku was created with the following configuration.
danmakuPattern.push({
name: "RIGHT ROTATING 4 x 3-WAY INTERMITTENT",
danmakuType: "MULTI_NWAY",
numberOfCannons: 3, // number of (pair in case of bi-directional danmaku) cannons
cannonAngle: 90, // direction in which the primary cannon faces.
cannonAngleRange: 25, // used to n-way type. angle range across which cannons are positioned.
numberOfNWAY: 4,
cannonAngularVelocity: 120,
numberOfShots: 5, // how many times to shoot the weapon in succession
stopShotsTime: 500,
// properties for individual bullets
bulletType: "NORMAL",
bulletSpeed: 200, // speed of bullets fired from cannon
timeBetweenShots: 100, // time between bullets in ms
bulletTexture: "bullet7" // specify the bullet image to be used,
});
As usual, here is the CodePen for your perusal and comment.
Comments