Scene wake data

I have a main scene with a number of sub-scenes (story dialog and mini-games). I’ve created a number of zones in my tile map to trigger the story scenes and mini-games. I’m having a couple of issues. When the player hits the zone the story starts as expected. However, when returning to the main scene.wake('thescene') the player is still moving, likely because they were pressing the key to move when the entered the zone. The player will stop after the up button is pressed and released, then the scene carries on as normal.

  1. How to I cancel the user input prior to launching the new scene.

  2. How can can set the player position to a specified location (exit point) when the main scene loads.

The new position is saved in the object layer of the map, so I just wanted to pass a data package back notifying the main scene of the exit point. this.scene.wake('mainscene', { exitpoint: 'theexit'})

Where is the data accessed on the main scene, like what method is called when it wakes up?

Here is the callback on overlap for the zone to trigger the new scene:

() => {
            if(this.player.data.values.entrance) return;
            this.player.body.setVelocityY(0);
            this.player.body.setVelocityX(0);
            this.player.setData('entrance', 'complete');
            this.scene.launch('story', { stage: 'entrance'});
            this.scene.sleep();
        }

When the child scene exits, I do something like this:

this.scene.stop();
this.scene.wake('mainscene', { exit: 'bumpercars_exit' });

Is there a better pattern to follow?

How did you add the movement key input?

In the create() method of the scene:

this.left = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT);
this.right = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT);
this.up = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.UP);
this.down = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN);

Then in the update:

    let animation = this.player.anims.currentAnim ? this.player.anims.currentAnim.key : 'down';
    let speed = 75;
    if(this.up.isDown) {
        this.player.body.setVelocityY(speed * -1);
        animation = 'walk-up';
    } else if(this.down.isDown) {
        this.player.body.setVelocityY(speed);
        animation = 'walk-down';
    } else {
        this.player.body.setVelocityY(0);
    }
    if(this.left.isDown) {
        this.player.body.setVelocityX(speed * -1);
        animation = 'walk-left';
    } else if(this.right.isDown) {
        this.player.body.setVelocityX(speed);
        animation = 'walk-right';
    } else {
        this.player.body.setVelocityX(0);
    }
    if( this.player.body.velocity.x === 0 && this.player.body.velocity.y === 0)
        animation = animation.replace('walk-', '');
    this.player.anims.play(animation, true);
    this.player.body.velocity.normalize().scale(speed);

@samme might have a better solution but just taking a quick look at the docs it looks like keys have a reset() method that will reset it back to the unpressed state: https://photonstorm.github.io/phaser3-docs/Phaser.Input.Keyboard.Key.html#reset__anchor

have not tested this but, in theory, you could reset all the player input keys when you do the scene wake

1 Like

Also try this.input.keyboard.resetKeys() in the scene that is sent to sleep.

2 Likes

I believe you can do this in scene create():

this.events.on('pause', this.input.keyboard.resetKeys, this.input.keyboard);
this.events.on('sleep', this.input.keyboard.resetKeys, this.input.keyboard);
1 Like

Yup, that did the trick.

Would this be the same mechanism to access the data on the wake event?

this.events.on('wake', this.onWake, this);

this.wake(sys, data) { do stuff with the data};

1 Like

I think so.

Yes, just tested. That worked as well.

If you’re restarting the scene then you’ll want to avoid adding duplicate event handlers:

const { keyboard } = this.input;

this.events
  .on('pause', keyboard.resetKeys, keyboard)
  .on('sleep', keyboard.resetKeys, keyboard)
  .once('shutdown', function () {
    this.events
      .off('pause', keyboard.resetKeys, keyboard)
      .off('sleep', keyboard.resetKeys, keyboard);
  }, this);

Below is just short form to help understand:
In another scene:
this.scene.wake(sceneName, {msg:“back from another scene”});

when this scene is awaken by the other scene:
this.events.on(‘wake’, function(sys, data){
console.log(data.msg);
});