Sprite stuck on final frame of animation

I have an animation ran from an event handler and the sprite gets stuck on the final frame. I can continue to click and it will replay the animation, but the sprite will still stay on the final frame. .setFrame doesn’t do anything.

here’s it is running:
https://keithileon.com

code:

Let me know if you guys have any ideas!! Thanks!

  pedestal.setInteractive({ useHandCursor: true })
  .on('pointerdown', (pointer) =>{
    if(!pointer.rightButtonDown()){
      if(this.cameras.main.backgroundColor.rgba == 'rgba(0,0,0,0)' 
      || this.cameras.main.backgroundColor.rgba == 'rgba(0,0,0,1)'){
        this.cameras.main.backgroundColor.setTo(255,255,255);
        pedestal.mask = pedMask;
      }else{
        this.cameras.main.backgroundColor.setTo(0,0,0);
        pedestal.clearMask();
      }
      pedestal.anims.play('pedActivate');
    }
  });

this.anims.create({
key: 'pedActivate',
frames: this.anims.generateFrameNumbers('pedestal', {start: 3, end: 0}),
frameRate: 10,
  });

If you want the animation to loop, you’re going to need to add repeat: -1 after the frame rate in the animation create statement. Is this what you were looking to do?

no my expected behavior is that the animation plays and goes from frame 0 -> 3 and then sits at frame 0 after its done. I’ve tried to use .setFrame(0) after the play command but it doesn’t seem to do anything.

I’ve worked around this by having the animation play in reverse 3->0. this way the sprite will sit after frame 0 once animation is complete. But this is a hack.

Hey Keith, try this:

pedestal.anims.setCurrentFrame(pedestal.anims.currentAnim.frames[0]);

yeah unfortunately that doesn’t work. not sure why, maybe because its being called from an event handler?

Ah, I think you may just need to stop the animation, then call that line of code. Here’s an example:

Go here and paste this:

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    pixelArt: true,
    width: 800,
    height: 600,
    scene: {
        preload: preload,
        create: create
    }
};

var game = new Phaser.Game(config);

function preload ()
{
    this.load.atlas('gems', 'assets/animations/diamond.png', 'assets/animations/diamond.json');
}

function create ()
{
    this.anims.create({ key: 'diamond', frames: this.anims.generateFrameNames('gems', { prefix: 'diamond_', end: 15, zeroPad: 4 }), repeat: -1 });
    var gem = this.add.sprite(400, 600, 'gems').play('diamond').setScale(4);

    gem.anims.stop();
    gem.anims.setCurrentFrame(gem.anims.currentAnim.frames[2]);
}

yeah so in this example that just sets the gem to that frame. and if i do something like this:

gem.anims.play('gems');
gem.anims.stop();
gem.anims.setCurrentFrame(gem.anims.currentAnim.frames[2]);

the gem doesn’t play the animation at all. it just sets it to that frame. same happens when i attempt this code in my project.

Apologies, I thought that was what you were intending to have happen. Are you just trying to have the animation loop?

no no i think i’ve either stumbled into a bug or i’m confused about some nuance or some part of this.

expected behavior:
player clicks object -> animation plays -> sprite sits idle at frame 0

actual behavior:
player clicks object -> animation plays -> sprite sits idle at the final frame of the animation just played

Okay, I’m picking up what you’re laying down now. I believe this is intended behavior, as some users may not want the animation to loop back to the first frame of the animation after it is finished. I would suggest just adding a listener to the sprite, so once the animation is complete, it either rewinds the animation or sets the frame back to zero.

1 Like

it seemed like the animation was getting stuck because once it played getCurrentKey() always returned it’s value and anims.getProgress() always returned 1. Which lines up with the sort of stuck behavior i was seeing.

soo i worked around this sort of. I used the anims.getProgress() in the update function to determine if the animation was running and if it wasn’t running currently i would have the sprite play a different idle animation:

  if (obelisks.obelisk1.sprite.anims.getCurrentKey() === 'obeliskActivate' 
  && obelisks.obelisk1.sprite.anims.getProgress() < 1) {}
  else{obelisks.obelisk1.sprite.anims.play('obeliskIdle', true)}

using this work around it would never play the final frame of the animation so i had to add a duplicate of the final frame in the sprite sheet to get it to actually appear.

idk if this is a bug or if something with my project resulted in this.

best of luck to anyone who comes across this!