Kurt Willrich
Kurt Willrich

Reputation: 65

Character atlas/spritesheet animation with user input not stopping on key up Phaser 3

I'm working on animating a character (using a texture atlas) with user input in Phaser 3 and I'm running into an issue with the animation not stopping when I release the respective arrow button. I've tried a few tactics, and some of them only partially work. The code below is what I use which works as intended in all respects, except the animation doesn't stop after I release the respective arrow key. Maybe I need logic with stopping animation once the key is lifted? Any suggestions? Thanks!

I've used this post as an example, but it prevents the character from moving diagonally: Sprite Sheet animation with arrow keys

update() {      

    this.hero.setVelocity(0,0);

    if (this.cursors.up.isDown) {
        this.hero.anims.play('walkUp', true); 
        this.hero.setVelocityY(-200);                     
    } 
    
    else if (this.cursors.down.isDown) {
        this.hero.anims.play('walkDown', true) 
        this.hero.setVelocityY(200);
    }         

    if (this.cursors.left.isDown) {    
        this.hero.anims.play('walkLeft', true)
        this.hero.setVelocityX(-200);
    } 

    else if (this.cursors.right.isDown) {
        this.hero.anims.play('walkRight', true)
        this.hero.setVelocityX(200);
    }                
}

Upvotes: 2

Views: 52

Answers (2)

winner_joiner
winner_joiner

Reputation: 14695

There are many ways to solve this. Your solution is ofcourse vaild, but here two alternative, the would keep your code abit shorter an easier to read.

Update: After re-reading your question, I see that for your specific useCase the Alternative 2 would be the needed solution. Just adding those 3 lines to your initial code, should do the trick.

Alternative 1

Since movement to the left and right override the up and down movement you could simply reorder the if/else blocks and chain them all as ob big if/else block and stop the animation in the final else. (Me from the future, your if's only override the animation)

update() {      

    this.hero.setVelocity(0,0);

    if (this.cursors.left.isDown) {    
        this.hero.anims.play('walkLeft', true)
        this.hero.setVelocityX(-200);
    } 
    else if (this.cursors.right.isDown) {
        this.hero.anims.play('walkRight', true)
        this.hero.setVelocityX(200);
    } 
    else if (this.cursors.up.isDown) {
        this.hero.anims.play('walkUp', true); 
        this.hero.setVelocityY(-200);                     
    } 
    else if (this.cursors.down.isDown) {
        this.hero.anims.play('walkDown', true) 
        this.hero.setVelocityY(200);
    }
    else {
        this.hero.anims.stop();
    }   
}

Alternative 2

Just check at the end of the update function, if the velocity -length is more or less equal to zero. (Since the object often don't really stop (because of gravity, gliding and some physics round stuff ) < 2 should be save/okay to use)

update() {      

    // ...  your initial code 
    if (this.hero.body.velocity.length() < 2) {
        this.hero.anims.stop();
    }   
     
}

In personally like the first altertive, but depending on your usecase, if you need to handle up/down and left/right independently, the later should be fine also.

Improved Alternative 2 but slightly longer, you could check for the key events instead of the velocity-length and it would be "cleaner".

if (!this.cursors.up.isDown &&
    !this.cursors.down.isDown &&
    !this.cursors.left.isDown &&
    !this.cursors.right.isDown ){
        this.hero.anims.stop();
}

Upvotes: 0

Kurt Willrich
Kurt Willrich

Reputation: 65

Well, through more research, I found out and answer. Basically, I separated the movement logic from the animation logic. This youTube video shows the troubleshooting involved starting around minute 9: https://www.youtube.com/watch?v=H-a_-uuM26E

Here's my final code that works:

this.hero.setVelocity(0,0);

    if (this.cursors?.up.isDown) {            
        this.hero.setVelocityY(-200);
    }          
    else if (this.cursors?.down.isDown) {
        this.hero.setVelocityY(200);
    } 
    if (this.cursors?.left.isDown) {    
        this.hero.setVelocityX(-200);
    }         
    else if (this.cursors?.right.isDown) {
        this.hero.setVelocityX(200);
    }
    if (this.cursors?.up.isDown) {            
        this.hero.anims.play('walkUp', true);  
    }          
    else if (this.cursors?.down.isDown) {
        this.hero.anims.play('walkDown', true) 
    } 
    else if (this.cursors?.left.isDown) {    
        this.hero.anims.play('walkLeft', true)
    }         
    else if (this.cursors?.right.isDown) {
        this.hero.anims.play('walkRight', true)
    } else {
        this.hero.anims.stop();
    }

Upvotes: 0

Related Questions