Rather than fire the bullets in all directions, what if we could aim the cannons across a predetermined range of directions? For example, if the primary cannon direction is downwards and the cannons' angle range is set to 90 degrees, and what we want is for one cannon to be aimed downwards and the other 2 cannons to be aiming 45 degrees to each side of the primary cannon.
That is what's called the n-Way danmaku. If the n-cannons rotate, then it is called a Rolling n-Way danmaku.
I have already created danmaku that fires bullets in n-directions. In previous danmaku code, I used for-loops to incrementally calculate the angle that the bullet should be fired in. When the cannons are to be spaced equally on both sides of the 'primary' cannon, the code becomes a little bit more complicated than simply placing n cannons all the way around. We can achieve the desired effect with the following code. The bold highlighted code is where the cannon directions are calculated.
fireweapon() {
for (let i = 0; i < this.numberOfCannons; i++) {
const bullet = bullets.getFirstDead(false);
if (bullet) {
const direction = this.angle + (i / (this.numberOfCannons-1) - 0.5) * this.cannonAngleRange;
bullet.fire({
x: this.x, // the bullet is fired from the middle of the Danmaku class (ie the spawner)
y: this.y, // the bullet is fired from the middle of the Danmaku class (ie the spawner)
shootAngle: direction, // direction in which the bullet is fired
bulletSpeed: this.bulletSpeed, // the speed of the bullet
bulletAcceleration: this.bulletAcceleration,
bulletAngle: direction, // make the bullet face the direction in which it is fired
bulletAngleVelocity: this.bulletAngleVelocity,
bulletType: this.bulletType
}); // end of bullet fire method
} // end of if statement which checks whether bullet is null
} // end of for loop
} // end of fireweapon method
There is however, a problem with this code. Specifically;
If there is only 1 cannon: Because the for loop calculates from the cannon the 'far left' first, the cannon aims at cannonAngleRange anti-clockwise to the direction of the 'primary' cannon
If the cannonAngleRange is 360 degrees: only n-1 cannons are created. This is because the 'far left' and the 'far right' cannons overlap.
The more mathematically minded programmer may come up with one line to cope with such anomalies, but I am not. So I will use the if statement to deal with these exceptional cases.
The section of the fireweapon function that has been revised is as below.
fireweapon() {
// first calculate the direction of each cannon and store in an array
const cannonAngles = [];
if (this.numberOfCannons <= 1) {
cannonAngles[0] = this.angle; // single cannon
}
else {
if (this.cannonAngleRange < 360) { // there is more than 1 cannon and angle < 360
for (let i = 0; i < this.numberOfCannons; i++) {
cannonAngles[i] = this.angle + (i / (this.numberOfCannons-1) - 0.5) * this.cannonAngleRange;
} // end of for loop
} // end of if statement checking cannons > 1 && cannonAngle Range < 360
else { // get here if there's more than 1 cannon, and Cannon angle range is 360
for (let i = 0; i < this.numberOfCannons; i++) {
cannonAngles[i] = this.angle + (360 / this.numberOfCannons) * i;
} // end of for loop
}
}
for (let i = 0; i < this.numberOfCannons; i++) {
const bullet = bullets.getFirstDead(false);
if (bullet) {
const direction = cannonAngles[i];
I've made some other minor changes to the code, the most significant of which is the addition of a angular acceleration property for the danmaku object.
Playing around with the various properties - which is now much easier with the use of TweakPane, give stunningly different results.
And that's it!
As usual, here is the CodePen Pen, for your perusal.
Comments