To make a cool-down animation I loaded a bunch of images. Is it feasible to use crop or tweens in Phaser 3 to do the job?

I'm trying to make a button with cool-down animation with Phaser 3. Here is the code.

class BootScene extends Phaser.Scene {
  constructor() {
    super();
  }
  
  preload() {
    this.load.path = 'https://raw.githubusercontent.com/liyi93319/phaser3_rpg/main/part1/assets/cooldown/';
    for (var i = 0; i < 16; i++) {
      this.load.image("cooldown" + i, "cooldown" + i + ".png");
    }
    this.load.image('magicAttack', 'magicAttack.png');

  }
  create() {
    this.add.image(100, 100, 'magicAttack').setScale(1)
    var cd = this.add.sprite(100, 100, 'cooldown1').setFlipX(false).setScale(1.5)
    let ani_frames = [];
    for (var i = 0; i < 16; i++) {
      ani_frames.push({ key: "cooldown" + i })
    }
    this.anims.create({
      key: 'right',
      frames: ani_frames,
      frameRate: 11,
      repeat: 0
    });
    cd.play('right');
        let circle2 = this.add.circle(100, 100, 150, 0x000000, 0).setScale(.2)
    cd.on('animationcomplete', () => {
      cd.setVisible(false)
    });
    // circle.lineStyle(10, 0xffffff, 0.9);
    circle2.setStrokeStyle(50, 0x000000, 1);
  }
  
}

var config = {
  width: 400,
  height: 300,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: {
        y: 0
      },
      debug: false // set to true to view zones
    }
  },
  backgroundColor: 0x000000,
  scene: [BootScene]
}

var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>

The code above works as expected but may be a little bit heavy-weight.

I know I can make a sprite-sheet but it's still in the image way. Is it feasible to use crop or tweens in Phaser 3 to do the job?

I know I could also put a DOM on the scene as using div to make the animation appears easier. However, it seems less Phaser style, right?


The code in this solution, is not much shorter, but a bit more cleaner/reuseable.
I would use the Phaser Masks (here is the link to the documentation)
And create a helper class, to abstract the whole masking and tweening logic out of the scene.

This helper class makes, the button also reuseable (the name for the helper class is maybe not the best).

The main idea is:

  • Create a mask the "masks" part of the image
  • Alter the mask with the tween, the tween alters only the percentage of the circle that is visible / hidden.
  • on the Tween Update Methode the Phaser Graphics Object (the mask) is rerendered.

Minor Update: corrected the mask starting angle, so that it matches with your example.

class Button {
    constructor(scene, gameObject){
        this.scene = scene;
        this.mask = scene.add.graphics().setVisible(false);
        this.mask.x = gameObject.x;
        this.mask.y = gameObject.y;
        gameObject.mask = new Phaser.Display.Masks.BitmapMask(scene, this.mask);
    }

    play(){
        this.scene.tweens.add({
            targets: this,
            hiddenPercent: { from: 0, to: 1 },
            ease: 'Power0',
            repeat: 0,
            duraton: 300,
            onUpdate: _ => this.render()
        });
    }

    render(){
        this.mask.clear();
        this.mask.fillStyle(0, 1);
        this.mask.beginPath();
        this.mask.slice(0, 0, 24, -Math.PI/2, (2 * Math.PI * this.hiddenPercent) -Math.PI/2 , false);
        this.mask.fillPath();
    }
}

class BootScene extends Phaser.Scene {
  preload() {
    this.load.image('magicAttack', 'https://raw.githubusercontent.com/liyi93319/phaser3_rpg/main/part1/assets/cooldown/magicAttack.png');
  }
  create() {
    let hand = this.add.image(100, 100, 'magicAttack').setScale(1);
    let button = new Button(this, hand);
    button.play();
  }
}

var config = {
  width: 400,
  height: 300,
  physics: {
    default: 'arcade',
    arcade: {
      gravity: {
        y: 0
      },
      debug: false // set to true to view zones
    }
  },
  backgroundColor: 0x000000,
  scene: [BootScene]
}

var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>