top of page
Search
cedarcantab

Danmaku using Phaser 3 (lesson 36): EXPLODE revisited

Updated: Nov 25, 2021


In lesson 34, I spun out the code to create the Curves.Path object to a separate function, as I re-worked the Draw danmaku code. As the mechanism for "expanding" pictures in the DRAW danmaku is essentially the same as the EXPLODE danmaku, I thought I would leverage the much more flexible code written for the DRAW danmaku, for the EXPLODE danmaku. In doing so, I can now have explosions in not only circles, but any of the patterns available in the DRAW function.


Leveraging the DRAW code

The modification does not require a lot of explanation, and I will simply paste the amended code.


First, the switch statement is as below. What used to be this.bulletTransformType is now this.bulletTransformClass, as I am now using this.bulletTransoformType to specify the type of picture to "explode" onto the screen.


The revised explode function is passed 4 parameters in addition to the scene context.


switch (this.bulletTransformClass) {
        
        case "EXPLODE":
          this.bulletConfig = this.setBaseConfig();
          this.explode(this, this.bulletTransformType, this.newBulletAngleRange, new Phaser.Math.Vector2(this.x,this.y),this.bulletTransformSize);
          this.switchOff();
          break;

And the revised explode method itself is as below. It is basically a rehash of the "DRAW" code, except it does not set many of the parameters relying on the defaults. The blue variables are new arrays created to hold the various information related to the exploded fragments.


  explode(scene, type="ARC", angleRange, bulletPos, vertices) {
 
    const shape = createPicture(type, 1, angleRange, vertices);

    cannonsFromCurve({
      curve: shape,
      heading: this.bulletConfig.bulletBearing,
      centre: bulletPos,
      numberOfPoints: this.newBulletCount,
      speed: this.newBulletSpeed,
      open: false, // if a open curve, set true, otherwise set to false so that n-th bullet doesnt overlap with 1st
      anglesArray: this.fragmentAngles,
      speedArray: this.fragmentSpeeds,
      cannonPositions: this.fragmentPositions,
    });

    for (let i = 0; i < this.fragmentAngles.length; i++) {
      const direction = this.fragmentAngles[i];
      const bullet = enemyBullets.getFirstDead(false);
      if (bullet) {
        this.bulletConfig.bulletBearing = direction;
        this.bulletConfig.bulletAngle = direction;
        this.bulletConfig.bulletSpeed = this.fragmentSpeeds[0][i];
        this.bulletConfig.bulletType = "NORMAL";
        bullet.fire(scene, this.bulletConfig); // end of bullet fire method
      } // end of if statement which checks whether bullet is null
    }
  } // end of explode method

And that's pretty much it to enable explosions into the different pictures created for the DRAW danmaku. The example danmaku at the top of this was created with the below parameter set.



danmakuPattern.push({
    name: "EXPLODING SMILEYs",
    danmakuConfig: {
      class: "PARALLEL", count:2,
      width: 200,
      angle:-90
    },
    cannonConfig: {
      yOffset: -200,
      numberOfShots: 5,
      stopShotsTime: 3000,        
    },
    bulletType: {
      class: "NORMAL",
      speed: 80, fireRate: 3000,
      texture: "roundMID", frame: 4
    },
    bulletTransform: {
      class: "EXPLODE", type: "SMILEY",
      stage1Time: 3000,
      count: 45,
      speed: 60,
      texture: "roundSML",
      frame: 0,
    }
  });

Random Bullet Speed

As I was playing around with the new functionality, I decided to add 2 new paramters/options.

  1. randomness to bullet speed: by setting bulletType.vRandom to a number above zero, you can now add randomness to the speed of each bullet. A random factor between minus vRandom/2 and plus vRandom/2 will be added to the specified bulletSpeed.

  2. decay in alpha value of bullet if lifeSpan is set: if bulletType.lifeAlpha is set to true, the alpha (i.e. opaqueness/transparency) of the bullet will disappear to zero if there is a limited lifespan set to the bullet.

The code for the 2nd option is as below.

 switch (this.bulletLife) {
      case -1:
        break;
      default:
        if (this.bulletLifeAlpha) {
          const alphaValue = (this.bulletLife - this.bulletTimer) / this.bulletLife;
          this.setAlpha(alphaValue >=0 ? alphaValue : 0)
        }
        if (this.bulletTimer > this.bulletLife) {
          this.switchOff();
        }
    }

I do not quite know why, but changing alpha values seem to affect bullets shot afterwards. This was fixed by adding a setAlpha(1) each time a new bullet is instantiated.


By combing vRandom and alpha decay to explosions and adding a bit of gravity creates the following which looks like fireworks! This is really outside the realm of danmaku patterns but never mind.




Fixing a bug

And I've realised there is a bug. A long time ago, I created a variable called this.numberOfShots which is actually 1 less than the real number of shots, so that it can be used for the repeatShotsTimer event (which counts from zero, hence to repeat n number of times, you need to set the repeat parameter to n-1). In the code sometimes I need to refer to n and sometimes I need to refer to n-1, and somewhere along the line I got confused. To avoid this confusion, I have now created a new variable called this.shotsCount to hold the parameter for the repeatShotsTimer event, and use the this.numberOfShots to hold the "real" number of shots.


Points for consideration

As I write this post I am still unsure of the handling of the "open" flag in the "explode" option. In the main danmaku, I have created a parameter to specify whether the curve object is a "open" or "closed" shape so that the 1st and last bullets do not overlap in the case of a closed object. I have not included such a parameter in the explode option - this is something to be fixed in the future.


And that's it for this post. Here is the CodePen for your perusal and comment.




Comments


記事: Blog2_Post
bottom of page