Home > Net >  Phaser3 - Music broken when starting a new scene
Phaser3 - Music broken when starting a new scene

Time:12-22

I'm super new to Phaser. I have a main platformer scene which plays a music. Everything was fine until I tried to add a start menu to the game. Here is relevant code of the menu:

public create(): void {
    super.create();

    this.newGameText = this.add
        .text( this.game.config.width / 2,  this.game.config.height / 2 - 72, "New game", { fontSize: "72px", color: "#fff" })
        .setOrigin(0.5, 0.5)
        .setInteractive();

    this.exitGameText = this.add
        .text( this.game.config.width / 2,  this.game.config.height / 2   72, "Exit game", { fontSize: "72px", color: "#fff" })
        .setOrigin(0.5, 0.5)
        .setInteractive();

    this.music = this.sound.add(Keys.Musics.MainMenu, { loop: true });

    this.music.play();
}

public update(time: number, delta: number): void {
    super.update(time, delta);

    this.newGameText.on(Keys.MouseEvents.PointerDown, () => this.startGame());
    this.exitGameText.on(Keys.MouseEvents.PointerDown, () => this.exitGame());
}

private startGame(): void {
    this.scene.start(Keys.Scenes.Game);
}

private exitGame(): void {
    this.game.destroy(true, true);
}

The game scene start playing its own music inside the create function, like this:

this.sound.play(Keys.Musics.Level1, {
    loop: true,
    volume: 0.3,
});

When I click on "New game", the game scene loads but the sound is aweful, I don't know how to describe it, but something wrong is going on.

If, inside the startGame() funciton of the main menu scene, I add this.music.destroy(), the next scene plays normally but I have the following error:

phaser.js:107083 Uncaught TypeError: Cannot read properties of null (reading 'disconnect')
at WebAudioSound.destroy (phaser.js:107083:1)

And here is the source code where it happens:

enter image description here

What am I doing wrong?

Sources can be found here.

Edit: if I remove the music from the main menu, the problem still persist

CodePudding user response:

The better solution is moving the two eventlistener hooks (setup should always be done in the init or create function). Just move two lines into the create function:

public create(): void {
    ...
    this.newGameText.on(Keys.MouseEvents.PointerDown, () => this.startGame());
    this.exitGameText.on(Keys.MouseEvents.PointerDown, () => this.exitGame());
}

the function will only be called "once", and that should be enough.

Checkout this flow chart of the phaser -game lifeCycle
btw.: the update function is called 60 times pre second.

CodePudding user response:

Ok I found out why.

this.newGameText.on(Keys.MouseEvents.PointerDown, () => this.startGame());

this is called ~100 times, so it's starting 100 scenes...

Here is how I fixed it:

private startGame(): void {
    if (!this.startingScene) {
        this.startingScene = true;
        this.music.stop();
        this.scene.start(Keys.Scenes.Game);
    }
}

Maybe there is a better way?

  • Related