Right now my game only restarts on the same tilemap. level-1 tilemap is loaded even if the key is level-2.
What do you think is the best way to make multiple levels?
I tried something like this but "level-2" does not work, tilemap does not update.
Does it make sense to make a new stage for each level? I tried that but it didn't work because I create the player in game.ts and I had problems importing it. Can't I solve this by restarting the scene.
game.ts :
import { Scene } from "phaser";
import Scenes from "./";
import { Player } from "../objects";
import GameManager from "../managers/gameManager";
import Level1Scene from "./level1scene";
export default class GameScene extends Scene {
//actors
private declare player: Player;
private declare currentScene: Scene;
// tilemap
private declare map: Phaser.Tilemaps.Tilemap;
// tilesets
private declare propsTileSet: Phaser.Tilemaps.Tileset;
private declare wallTileset: Phaser.Tilemaps.Tileset;
private declare bgTileset: Phaser.Tilemaps.Tileset;
// tilemap layers
private declare propsLayer: Phaser.Tilemaps.TilemapLayer;
private declare bgLayer: Phaser.Tilemaps.TilemapLayer;
private declare wallsLayer: Phaser.Tilemaps.TilemapLayer;
private declare currentMap: string;
constructor() {
super({
key: Scenes.GameScene.key,
});
}
init() {
this.game.events.emit("react__onGameStart");
}
create() {
this.createTiles();
this.createLayers();
this.map.setCollision([1025, 1026]);
this.createPlayer();
this.createFullscreenButton();
this.cameras.main.startFollow(this.player);
this.cameras.main.setZoom(2);
}
private createFullscreenButton() {
const fullscreenButton = this.add
.sprite(this.cameras.main.width, this.cameras.main.height, "fullScreen")
.setInteractive();
fullscreenButton.on("pointerup", () => {
this.toggleFullscreen();
});
}
private toggleFullscreen() {
if (this.scale.isFullscreen) {
this.scale.stopFullscreen();
} else {
this.scale.startFullscreen();
}
}
update(time: number, delta: number): void {
this.player.update();
this.physics.collide(this.player, this.wallsLayer);
this.physics.collide(this.player, this.propsLayer);
this.physics.add.collider(this.propsLayer, this.player, (player, tile) => {
if ((tile as Phaser.Tilemaps.Tile).index == 37) {
console.log("Collision with tile index 37");
GameManager.instance.nextlevel();
GameManager.instance.currentLevelKey;
this.scene.restart();
}
});
}
private createTiles(): void {
this.map = this.make.tilemap({
key: GameManager.instance.currentLevelKey,
});
this.propsTileSet = this.map.addTilesetImage("props")!;
this.wallTileset = this.map.addTilesetImage("ground")!;
}
private createLayers() {
this.add.image(0, 0, "bg").setOrigin(0, 0);
this.propsLayer = this.map.createLayer("props", this.propsTileSet, 0, 0)!;
this.wallsLayer = this.map.createLayer("ground", this.wallTileset, 0, 0)!;
this.propsLayer.setCollisionBetween(36, 40);
}
private createPlayer(): void {
this.player = new Player({
key: "player",
scale: 1,
scene: this,
tag: "player",
texture: "atlas",
x: 50,
y: 0,
afterCreate: () => {
console.log("Player is created");
},
});
}
}
gameManager :
import { Scene } from "phaser";
import { Player } from "../objects";
import Scenes from "../scenes";
export default class GameManager {
getScene(currentLevelKey: string) {
throw new Error("Method not implemented.");
}
private static _instance: GameManager;
private player: Player | null;
private declare levels: string[];
private declare _currentLevelKey: string;
private declare currentLevel: integer;
private constructor() {
this.player = null;
this.currentLevel = 1;
this.levels = ["level-1", "level-2"];
}
public static get instance(): GameManager {
if (!GameManager._instance) {
GameManager._instance = new GameManager();
}
return GameManager._instance;
}
public setPlayer(player: Player): void {
this.player = player;
}
public getPlayer(): Player | null {
return this.player;
}
public get currentLevelKey(): string {
return this.levels[this.currentLevel];
}
public nextlevel() {
if (this.currentLevel < this.levels.length - 1) {
this.currentLevel += 1;
}
}
}
Your code looks good, the only thing that doesn't seem to fit is this.currentLevel = 1;
in the constructor
, if you want the first level to be called you would have to set this.currentLevel = 0;
And you need to move this line(s) into the create
function
this.physics.add.collider(this.propsLayer, this.player, (player, tile) => {
if ((tile as Phaser.Tilemaps.Tile).index == 37) {
console.log("Collision with tile index 37");
GameManager.instance.nextlevel();
GameManager.instance.currentLevelKey;
this.scene.restart();
}
});
because this.physics.add.collider
add's an eventHandler action, this should be done only once. The update
function is called multiple times.
Tipp: if you create a minimal viable example, it might be easier to debug. here a short guide from StackOverlfow, that might help.