Steps

Switching Levels


Introduce the ability to end a level and begin a new one within the game play.

Step 1 — In the Boot.ts File, Create a New ‘Door’ Object

Load the spritesheet and audio for the door in the preload() method.

// Boot.ts
export class Boot extends Phaser.Scene {
//...

preload() {
//...

this.load.spritesheet('door', 'images/door.png', {
frameWidth: 42,
frameHeight: 66,
});

//...
this.load.audio('sfx:door', 'audio/door.wav');
}

//...
}

Step 2 — Incorporate the ‘Door’ in Level.ts

Create a property in the Level class for a door.

  • This should be of type any.
// Level.ts

export class Level {
hero!: Hero;
spiders: Spider[] = [];
coinIcon: any;
keyIcon: any;
key: any;
door: any;

//...
}

Add a method to spawn the door as a part of the bgDecoration group.

  • Implement this method within the loadLevel() method.
// Level.ts

export class Level {
//...

loadLevel(data) {
this.spawnBG();
this.spawnDoor(data.door);
this.spawnPlatforms(data.platforms);
//...
}

spawnDoor(door) {
this.door = this.groups.bgDecoration.create(door.x, door.y, 'door');
this.door.setOrigin(0.5, 1);
this.door.body.allowGravity = false;
this.addPhysics(this.door);
}

//...
}

Step 3 — In the Play.ts File, Set Conditions for a Level to Change

Add a property outside of the class for the level count, add a door property to the class (of the type any), and change the currentLevel property to 1.

// Play.ts

const LEVEL_COUNT = 2;

export class Play extends Phaser.Scene {
hero!: Hero;
spiders!: Spider[];
level!: Level;
currentLevel: integer = 1;
score: integer = 0;
key: any;
door: any;
coinIcon: any;
keyIcon: any;
hasKey: boolean = false;

//...
}

Add the door to the mapProps() method.

// Play.ts

export class Play extends Phaser.Scene {
//...

private mapProps() {
const props = [
'hero',
'groups',
'spiders',
'coinIcon',
'keyIcon',
'key',
'door',
];

props.forEach((prop) => (this[prop] = this.level[prop]));
}
}

Create a method called exitThroughDoor() that responds to the hero character moving over the door and plays a sound. This should also trigger another method: gotoNextLevel().

  • Once the exitThroughDoor() method is created, add it to the initPhysics() method as an overlap scenario between the hero and door objects.
// Play.ts

export class Play extends Phaser.Scene {
//...

initPhysics() {
//...

this.physics.add.overlap(
this.hero,
this.door,
this.exitThroughDoor,
(hero, door) => this.hasKey && hero.body.touching.down,
this
);
}

exitThroughDoor(hero, door) {
this.sound.play('sfx:door');
this.gotoNextLevel();
}

//...
}

Setup the logic for the gotoNextLevel() method.

  • This should access the currentLevel and check to see if it is less than the LEVEL_COUNT property.
  • If it is, then currentLevel should increment by 1.
  • If it is not, then currentLevel should be set to 1 so that the player goes back to the first level of the game.

The method should end by calling this.reset() to enact the camera animations.

// Play.ts

export class Play extends Phaser.Scene {
//...

gotoNextLevel() {
this.currentLevel =
this.currentLevel < LEVEL_COUNT ? ++this.currentLevel : 1;

this.reset();
}

//...
}

Step 4 — Change the Dynamics for How a Level Ends

In the Play.ts file, change the gameOver() method so that it no longer has the camera animations and move the camera animations to the reset() method.

  • Also, add a call to the gotoLevel() method in the reset() method.

The gotoLevel() method accesses the loadLevel() method where data is retrieved from the cache with a key referring to JSON data.

// Play.ts
export class Play extends Phaser.Scene {
//...

reset() {
this.score = 0;
this.hasKey = false;

this.cameras.main.fade(1000);
this.cameras.main.on('camerafadeoutcomplete', (camera, effect) => {
this.scene.start('Play');
this.gotoLevel(this.currentLevel);
});
}

gameOver() {
this.hero.die();
this.reset();
}

gotoLevel(level) {
this.level.loadLevel(this.cache.json.get(**level:${level}**));
}
//...
}

Essentially, we have changed the way a level ends so that:

  • When any reset() occurs, the score is set to 0, the player does not have a key, the camera fades out for one second, it restarts the Play dynamics, and goes to the currentLevel (which could be different based on what has happened in the game).
  • If gameOver() is triggered, the die mechanics occur and the reset() method is called.

Checkpoint

  1. There should now be a door on the screen.
  2. When the player passes the door without the key, nothing should happen.
  3. When the player passes the door with the key, the level should end and take the player to the next level.
  4. If the player completes the final level, it should take the player back to level one.

Note: If you would like to see the game without the physics debugging, return to the Config.ts file and comment out the debug key.

import Phaser from "phaser";
import { Boot } from './Boot';
import { Play } from './Play';

export const gameConfig = {
type: Phaser.AUTO,
width: 960,
height: 600,
roundPixels: true,
backgroundColor: 0x000000,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
// debug: true,
},
},
scene: [Boot, Play],
};
< Back Home