Animations for the main character
Right now we have a few animated sprites in the game: the coins and the enemy spiders. But none for the main character! We are going to implement them now.
This is the character's spritesheet and the animations in it:
- Stopped: frame #0
- Running: frames #1 - #2
- Jumping (upwards): frame #3
- Falling: frame #4
There's also a dying/hit animation in the spritesheet, but we will implement it in a later stage.
As you can see, this can be a bit complex, so the approach that we will follow to handle animations for the main character is to check every frame which animation should be active and, if it's different, we'll play another one.
Tasks
Add the new animations
Previously we had
hero_stopped.png
assigned to thehero
key, loaded as an image. We need to get rid of that, so delete this line in thepreload
:PlayState.preload = function () { // delete this line below this.game.load.image('hero', 'images/hero_stopped.png'); };
Now we need to load the new spritesheet into the
hero
key:PlayState.preload = function () { // ... this.game.load.spritesheet('hero', 'images/hero.png', 36, 42); // ... };
Add the new animations in the
Hero
constructor:function Hero(game, x, y) { // ... this.animations.add('stop', [0]); this.animations.add('run', [1, 2], 8, true); // 8fps looped this.animations.add('jump', [3]); this.animations.add('fall', [4]); }
Calculate which animation should be playing
This is the new
Hero
method that will return the name of the animation that should be playing:Hero.prototype._getAnimationName = function () { let name = 'stop'; // default animation // jumping if (this.body.velocity.y < 0) { name = 'jump'; } // falling else if (this.body.velocity.y >= 0 && !this.body.touching.down) { name = 'fall'; } else if (this.body.velocity.x !== 0 && this.body.touching.down) { name = 'run'; } return name; };
Note how in the falling state we are both checking that the vertical velocity is positive (it goes downwards) and that the main character is not touching a platform. Why? Because when the character is on the ground it still has a vertical velocity caused by the gravity. The character doesn't fall because there is a body blocking them, not because their vertical velocity is zero.
We will create an
update
method forHero
in which we will check which animation should be playing and switch to a new one if necessary. Remember thatupdate
methods inPhaser.Sprite
instances get called automatically each frame!Hero.prototype.update = function () { // update sprite animation, if it needs changing let animationName = this._getAnimationName(); if (this.animations.name !== animationName) { this.animations.play(animationName); } };
Try it now in the browser! Run, jump around… You should be able to see all the animations in place. And a little glitch: the character does not face the right direction when moving left.
Make the character face the right direction
It may sound weird, but usually in game development flipping (or mirroring) an image is achieved by applying a negative scale to the image. So applying a scale of
-100%
horizontally will flip the image of the character to face to the left.Add this to the
move
method, since we know the direction in that moment:Hero.prototype.move = function (direction) { // ... if (this.body.velocity.x < 0) { this.scale.x = -1; } else if (this.body.velocity.x > 0) { this.scale.x = 1; } };
In Phaser scales are normalized, so
0.5
means50%
,1
means100%
and so on.
The final result is the main character facing the right direction when moving.
Checklist
- The main character shows different animations or images for the following actions: not moving, running, jumping and falling.
- The main character faces the correct direction when moving either left or right.
Download
Are you stuck? Take a look at the source code for this step.