top of page
Search
cedarcantab

Danmaku using Phaser 3 (lesson 40 Part 1): Defining Bullet Texture as Arrays

Updated: Dec 4, 2021

I have come a long way in terms of adding parameters to define the danmaku pattern, the way bullets are fired via the cannonConfig, and how the bullets behave (bulletConfig, and bulletTransform). However, in essence once the individual parameters are set, they remain set. The most obvious example is the texture of bullets - yes, we can change the texture by using bulletTransform, but we cannot say change the texture of consecutive bullets or the arms of nways for example. This is what we tackle in this post - the ability to read an array for parameters.



A few bug fixes first

But first things first. A few "fixes" before we get to the meat of this post.


danmakuSpokes function to handle multi-nways with cannons in each nway set to 1

I have changed the danmakuSpokes function which creates the cannon spokes array for multi-nways slightly. The revision make it cope with multi-nways with danmakuConfig.countA set to 1 and danmakuConfig.multiple set to anything other than 1 (==> same as countA being set to n). In the prevous verson of the code, if countA is set to 1, the angles array was corrupt.


ability to specify whether shape is closed or open for explode method

I have now included a parameter bulletTransform.flag to specify whether the "shape" of the explosion is closed or not - in the previous version fo the code, it was assumed that unless the shape was an "arc" shapes were all closed. This worked, but I did not like it. Unless specified, it default to false (i.e. not open, ie closed).


Now, onto the main topic of this post.


Ability to read arrays for parameters

Let's tackle bullet textures first.


Ability to specify bullet texture for each time fireShot is called

bullet texture is defined by this.bulletTexture and this.bulletFrame. In the previous version of the code, this.bulletTexture is always expected to be a string, and this.bulletFrame is always expected to be a number. We want the code to be able to accept arrays. This is achieved with the following simple method, which returns the the variable as is it is not an array (ie string or number). If it is an array, it picks the item from the array based on the counter, which by default is this.repeatShotsCount


  readParam(param, count= this.repeatShotsCount) {
    if (Array.isArray(param)) {
      return param[count % param.length]
    } else {
      return param
    }
  } // end of readParam method

When calling the fire method of bullet class, instead of passing this.bulletTexture and this.bulletFrame directly, we do so via the readParam method. The following extracts are what achieves this. We first assign the two variables to another object, for easier manipulation.

const bulletImage = {texture: this.readParam(this.bulletTexture), frame: this.readParam(this.bulletFrame)};

and within the code that calls the fire method;


// now cycle through each cannon
for (let j = 0; j < this.cannonShotSpeeds[i].length; j++) {
   
....
   bulletTexture: this.readParam(bulletImage.texture, j),
   bulletFrame: this.readParam(bulletImage.frame, j),

You will note that we call the readParam method twice. This is so that we can have nested arrays. If we pass a non-nested array, then we can control the bullet texture each time the fireShot function is called. For example, the pattern at the top of this post was created with the following parameter set:


  danmakuPattern.push({
    name: "MULTI-COLOR 20-WAY",
    danmakuConfig: {
      countA: 20, 
    },
    cannonConfig: {
      fireRate: 500,
    },
    bulletConfig: {
      speed: 50, 
      texture: "tripodMID", frame: [11,10,9,8,7,6,5,4,3,2,1,0],
    },
  });  

If the array is nested, then we can control each of the cannons (ie each "arm" of an nway), like the example below.


  danmakuPattern.push({
    name: "MULTI-COLOR 20-WAY",
    danmakuConfig: {
      countA: 8, angularVelocity: 30,   
    },
    cannonConfig: {
      fireRate: 500, 
    },
    bulletConfig: {
      speed: 50, 
      texture: "tripodMID", frame: [[0,1,2,3,4,5,6,7]],
    },
  });  


The above examples only changes the spritesheet frames, but you can of course change both the texture and frame with each fireShot.




With a little bit of perseverance with the nesting you can create quite sophisticated patterns.


  danmakuPattern.push({
    name: "INTERMITTENT 20-WAY",
    danmakuConfig: {
      countA: 20,
      angle: 90,
    },
    cannonConfig: {
      numberOfShots: 5, // how many times to shoot the weapon in succession
      stopShotsTime: 500,
      fireRate: 200,    
    },
    // properties for individual bullets
    bulletConfig: {
      class: "NORMAL" , speed: 80,
      texture: [["roundMID","oblongMID","oblongMID"],["oblongMID","roundMID","oblongMID"],["oblongMID","oblongMID","roundMID"],["oblongMID","roundMID","oblongMID"],["roundMID","oblongMID","oblongMID"]],
      frame: [1,5,0,5,1],  
    },
  });  



The technique for passing arrays as parameters can be extended to other parameters with relative ease. In the next post, I continue along these lines.




Comments


記事: Blog2_Post
bottom of page