Best way to switch to new level

I’m implementing level change on a game with tilemap and bunch of groups, colliders etc.

What I’ve tried is making a clearLevel function that:

  • disables player body
  • removes all colliders
  • calls destroy on all the groups and sprites, tilemap

Then I open a level by creating everything again and enabling the colliders and the player body at the very end.

Changing level is triggered by colliding with a sprite that is in a group. Everything seems to work fine for most of the time but sometimes there is an error thrown after opening a new level, creating all the content and enabling the player. It seems to be about collider handler looking for group children to check against but finding none. Since it only happens sometimes it seems like it’s somekind of timing issue with destroying and creating everything, but difficult to pinpoint why. Could it be that sprite I collide with to change levels is destroyed and some collide handler is still looking for it even after removing all the colliders?

‘Group.js:717 Uncaught TypeError: Cannot read property ‘contains’ of undefined
at PhysicsGroup.contains (Group.js:717)
at World.collideSpriteVsGroup (World.js:2071)
at World.collideHandler (World.js:1946)
at World.collideObjects (World.js:1873)
at Collider.update (Collider.js:143)
at World.step (World.js:1083)
at World.update (World.js:1034)
at EventEmitter.emit (index.js:203)
at Systems.step (Systems.js:369)
at SceneManager.update (SceneManager.js:562)’

Is it worthwhile to make your own cleaner like this or should I try using another parent scene that destroys the whole game scene every time? Or is there some better Phaser way of doing this?

2 Likes

This is how I do it and always did:
(Restarting the whole scene every time)

export default class MainScene extends Phaser.Scene {
  currentLevel

  constructor() {
    super({ key: 'MainScene' })
  }

  init(props) {
    const { level = 0 } = props
    this.currentLevel = level
  }

  preload() {
    // load the correct map based on this.currentLevel
  }

  create() {
    console.log(this.currentLevel)

    // start the next level after 2.5 seconds
    this.time.addEvent({
      delay: 2500,
      callback: () => this.scene.restart({ level: this.currentLevel + 1 })
    })
  }
}

Maybe my Phaser 3: Platformer Example will help you too!

4 Likes

Thanks, is that delay necessary for it to work well?

No, of course not. In your game you would only look for a collision or overlap and then only use this.scene.restart({ level: this.currentLevel + 1 }).

(I use the time event only for the demo)

2 Likes

Over and over and over, for days now I’ve been searching and just coming up with the same handful of results every single time, no matter how it’s worded. The documentation for this framework is crap. It’s rubbish. The community is even worse. What the hell is that download all about? Thousands of files for a simple example of how to switch between screens? You would think it an easy task, you would think at least somebody has a working example, just a few minimal screens you can switch between, but no. It’s little bits of information with elements of go figure the rest out for yourself. The documentation on Phaser 3 is so bad that by the time you’ve learned how to use it, you may as well have done all the math yourself. There are questions, important questions that have been left unanswered in this forum for well over a year, not even the original developers have bothered answering them. One of the worst frameworks and biggest wastes of time I’ve had the misfortune of stumbling on for years.

1 Like

@james1

4 Likes

I know the pain in one night. Uffff

The best way is

this.scene.start('anotherScene');

or

this.scene.restart();