Dying
This part of the app will incorporate adding a dynamic for a level ending that includes many of the processes we’ve handled in previous sections all combined together.
Step 1 — Preload Sound Effects
Update the preload() method in the Boot.ts scene to load sound effects for when a hero character is hit by an enemy spider with 'sfx:stomp'.
// Boot.ts
export class Boot extends Phaser.Scene {
//...
preload() {
//...
this.load.audio('sfx:jump', 'audio/jump.wav');
this.load.audio('sfx:coin', 'audio/coin.wav');
this.load.audio('sfx:stomp', 'audio/stomp.wav');
}
}
Step 2 — Update the Animations Map to Include a Key for the “dying” Animation on the Hero Object.**
// Animations.ts
export class Animations {
map = {
spider: {
crawl: 'spider:crawl',
},
hero: {
stop: 'hero:stop',
run: 'hero:run',
jump: 'hero:jump',
fall: 'hero:fall',
dying: 'hero:dying',
},
elements: {
coin: {
rotate: 'coin:rotate',
},
},
};
//...
}
Add the animation to the initAnimations() method:
// Animations.ts
export class Animations {
//...
initAnimations(scene: Phaser.Scene) {
//...
scene.anims.create({
key: 'hero:dying',
frames: scene.anims.generateFrameNumbers('hero', { start: 5, end: 6 }),
frameRate: 12,
repeat: 4,
});
//...
}
}
Step 3 — Create the Conditions for the Animation to Change in Hero.ts
Start by adding a property called dead and set it to false.
// Hero.ts
export class Hero extends Phaser.Physics.Arcade.Sprite {
keys!: Phaser.Types.Input.Keyboard.CursorKeys;
dead = false;
animations!: any;
//...
}
Add a condition to the update() method of the Hero class to check if the hero is dead — we will include a return statement with no logic.
- Remember, the update() method will check the state of the game during every frame.
- Make sure to place this if() statement separate from the other one that checks for key presses. Essentially, the update() method should now include two separate if() functions.
// Hero.ts
export class Hero extends Phaser.Physics.Arcade.Sprite {
//...
update() {
if (this.dead) return; // Hero is dead... do nothing
//...
}
//...
}
Create a method for when the hero dies.
- This should set the dead property to true and play the animation.
- Once dead is true — we will trigger the condition we created in the update() method that “does nothing”.
export class Hero extends Phaser.Physics.Arcade.Sprite {
//...
die() {
this.dead = true;
this.anims.play(this.animations.dying, true);
}
//...
}
Step 4 — Spider Dying
Update the animations map to include a key for the dying animation for the spider.
// Animations.ts
export class Animations {
map = {
spider: {
crawl: 'crawl',
dying: 'spider:dying',
},
hero: {
//...
},
elements: {
//...
},
};
//...
}
Add the spider:dying animation to the initAnimations() method:
// Animations.ts
export class Animations {
//...
initAnimations(scene: Phaser.Scene) {
//...
scene.anims.create({
key: 'spider:dying',
frames: scene.anims.generateFrameNumbers('spider', {
frames: [0, 4, 0, 4, 0, 4, 3, 3, 3, 3, 3, 3],
}),
frameRate: 12,
repeat: 0,
hideOnComplete: true,
});
//...
}
}
Step 5 — In the Spider.ts File, Add a dead Property
Just like the hero, set this initially to false.
// Spider.ts
export class Spider extends Phaser.Physics.Arcade.Sprite {
direction = Directions.right;
animations!: any;
dead = false;
//...
}
Modify the update() method in the Spider class to check if the spider is not dead and call the live() method if it is not dead (i.e., if dead === false).
- This should involve replace the current logic in the update() method.
Then, in the die() method, set the dead property to true and disable the body while calling the anims.play() method to run the dying animation for the spider.
// Spider.ts
export class Spider extends Phaser.Physics.Arcade.Sprite {
//...
update() {
if (!this.dead) {
this.live();
}
}
die() {
this.dead = true;
this.disableBody();
this.anims.play(this.animations.dying, true);
}
//...
}
Step 6 — Create the Gameplay for Dying
In the Play.ts file, update the initPhysics() method to add an overlap between the hero character and the spiders.
- Add a doBattle() method that takes arguments of hero and spider.
// Play.ts
export class Play extends Phaser.Scene {
//...
initPhysics() {
//...
this.physics.add.overlap(
this.hero,
this.groups.spiders,
this.doBattle,
undefined,
this
);
}
doBattle(hero, spider) { }
//...
}
Update the doBattle() method to check if the spider is touching the hero from the top and if the hero is touching the spider from the bottom. Essentially, if the hero has jumped on top of the spider.
- If so, this should destroy the spider.
- Anything else means the spider ran into the hero and the hero should be destroyed.
// Play.ts
export class Play extends Phaser.Scene {
//...
doBattle(hero, spider) {
if (spider.body.touching.up && hero.body.touching.down) {
// The hero landed on the spider
} else {
// The spider ran into the hero
}
}
//...
}
Add the outcome of the hero jumping on the spider to destroy it.
- This should include the sound effect sfx:stomp and calling the die() method.
If the hero is touched by the spider in any other condition, call the gameOver() method.
- Write the method to access the hero class and call the die() method.
// Play.ts
export class Play extends Phaser.Scene {
//...
doBattle(hero, spider) {
if (spider.body.touching.up && hero.body.touching.down) {
this.sound.play('sfx:stomp');
spider.die();
} else {
this.gameOver();
}
}
gameOver() {
this.hero.die();
}
//...
}
Step 7 — Create Methods for the Camera in the Play.ts File
Add an initCamera() to the Play class.
- In the create() method, call the initCamera() method.
In the initCamera() method, set the bounds of the camera to the size of the level and flash the camera.
- This causes the camera to fade in from black — giving a nice effect to the game.
// Play.ts
export class Play extends Phaser.Scene {
//...
create() {
console.log('Play.create()');
this.initAnimations();
this.initLevel();
this.initCamera();
this.initPhysics();
}
//...
initCamera() {
this.cameras.main.setBounds(0, 0, 960, 600);
this.cameras.main.flash();
}
//...
}
When the hero character dies, fade the camera out and restart the scene.
Put this in the gameOver() method.
// Play.ts
export class Play extends Phaser.Scene {
//...
gameOver() {
this.hero.die();
this.cameras.main.fade(1000);
this.cameras.main.on('camerafadeoutcomplete', (camera, effect) => {
this.scene.restart();
});
}
//...
}
Checkpoint
- If the hero character jumps on a spider, the spider should be destroyed with an animation.
- If a spider touches the hero character, a flashing animation should occur and the screen should fade to black, followed by the level restarting.