Search code examples
javascriptphaser-frameworkscene

Problem returning back to Scene from another Scene Phaser 3


I am new to Phaser and I want to get some help or explanation associated with my problem.

So, I wanted to switch the scene to the next scene when my character reaches a certain point. In this case the end point of the world bounds (scene).

I wrote this in update():

//sceneA
if(postava.x < 0)
{ 
    this.scene.switch("rozcestnikScena");
}

This block of code works great and switches to the next scene.

Then I wrote in the second scene in update():

//sceneB
if(postava.x > 800)
{
    this.scene.switch("uvodniScena");
}

Now, when it switches to the first scene (sceneA), my character appears in a running loop and cannot be controlled and runs to the world bounds and the scene stays the same.

I read many tutorials, but I can't figure out why the character cannot be controlled and acts on its own.

Any help is much appreciated!

More code:

1.Scene

let zeme;
let postava;
let klavesnice;
let auto;
let keyA;
let keyW;
let keyS;
let keyD;

class JSScenaPlay extends Phaser.Scene {
    constructor() {
        super("uvodniScena");
    }

    create() {

        this.gzDialog.setText("Ah heck, my car has broken down. I need to go to a nearby town and find somebody who can help.");
        this.background = this.add.image(0, 0, "pozadiObloha");
        this.background.setOrigin(0, 0);

        zeme = this.physics.add.staticGroup();
        zeme.create(config.width / 2, 675, "zeme").refreshBody();

        postava = this.physics.add.sprite(20, 556, "postava");
        postava.setBounce(0.1);
        postava.setDepth(5);

        auto = this.physics.add.image(config.width / 2 + 325, 562, "auto");
        auto.setScale(1.5);
        auto.setDepth(1);

        this.anims.create({
                key: "right",
                frames: this.anims.generateFrameNumbers("postava", { start: 5, end: 8 }),
                frameRate: 10,
                repeat: -1
            });

        this.anims.create({
                key: "turn",
                frames: [{ key: "postava", frame: 4 }],
                frameRate: 20
            });

        this.anims.create({
                key: "left",
                frames: this.anims.generateFrameNumbers("postava", { start: 0, end: 3 }),
                frameRate: 10,
                repeat: -1
            });

        postava.body.setGravityY(50);

        this.physics.add.collider(postava, zeme);

        this.physics.add.collider(auto, zeme);
        this.physics.add.collider(postava, auto, diaOkno, null, this);
        auto.setPushable(false);

        klavesnice = this.input.keyboard.createCursorKeys();

        function diaOkno(postava, auto) {
            postava.anims.play("turn");
            this.gzDialog.visible;
            this.gzDialog.setText("I need to find some car mechanic to repair the engine.");
        }

        keyA = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
        keyS = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
        keyD = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
        keyW = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
    }

    update() {
        //pohyb doleva
        if (keyA.isDown || klavesnice.left.isDown) {
            postava.setVelocityX(-100);
            postava.anims.play("left", true);
        }
        //pohyb doprava
        else if (keyD.isDown || klavesnice.right.isDown) {
            postava.setVelocityX(100);
            postava.anims.play("right", true);
        }
        else {
            postava.setVelocityX(0);
            postava.anims.play("turn");
        }

        //skok
        if (keyW.isDown && postava.body.touching.down || klavesnice.up.isDown && postava.body.touching.down) {
            postava.setVelocityY(-250);
        }

        if (postava.x < 0) {
            this.scene.switch("rozcestnikScena");
        }
    }
}

2.Scene

class JSScenaPlayRozcestnik extends Phaser.Scene {
    constructor() {
        super("rozcestnikScena");
    }

    create() {

        this.background = this.add.image(0, 0, "pozadiObloha");
        this.background.setOrigin(0, 0);

        zeme = this.physics.add.staticGroup();

        zeme.create(config.width / 2, 675, "zeme").refreshBody();

        postava = this.physics.add.sprite(800, 556, "postava");

        postava.setBounce(0.1);

        postava.setDepth(5);

        klavesnice = this.input.keyboard.createCursorKeys();

        this.physics.add.collider(postava, zeme);

        this.anims.create({
                key: "right",
                frames: this.anims.generateFrameNumbers("postava", { start: 5, end: 8 }),
                frameRate: 10,
                repeat: -1
            });

        this.anims.create({
                key: "turn",
                frames: [{ key: "postava", frame: 4 }],
                frameRate: 20
            });

        this.anims.create({
                key: "left",
                frames: this.anims.generateFrameNumbers("postava", { start: 0, end: 3 }),
                frameRate: 10,
                repeat: -1
            });

        postava.body.setGravityY(50);
    }
    update() {
        //pohyb doleva
        if (keyA.isDown || klavesnice.left.isDown) {
            postava.setVelocityX(-100);
            postava.anims.play("left", true);
        }
        //pohyb doprava
        else if (keyD.isDown || klavesnice.right.isDown) {
            postava.setVelocityX(100);
            postava.anims.play("right", true);
        }
        else {
            postava.setVelocityX(0);
            postava.anims.play("turn");
        }

        //skok
        if (keyW.isDown && postava.body.touching.down || klavesnice.up.isDown && postava.body.touching.down) {
            postava.setVelocityY(-250);
        }

        //zavření dialogového okna
        if (this.gzDialog.visible) {
            this.physics.pause();
            postava.anims.play("right");

            if (klavesnice.space.isDown) {
                this.gzDialog.display(false);
                this.physics.resume();
            }
        }

        if (postava.x > 800) {
            this.scene.switch("uvodniScena");
        }

    }
}

Solution

  • I assume the problem is when you switch back, the "player" is stil over the magic switch line (800px).

    You would onl have to move the player before switching the scene, so that when you come back the switch is not triggered again and again in a loop.

    Here is a optimized, small demo:
    here the player will moved behind the switch line before switching the scene.
    (I used inheritance to avoid code duplication)

    document.body.style = 'margin:0;';
    
    class PlayerScene extends Phaser.Scene {
        create() {
            let player = this.add.rectangle(10, 50, 20, 20, 0xffffff)
                .setOrigin(0);
           
            this.physics.add.existing(player);
            this.player = player.body;
            this.player.setCollideWorldBounds(true);
            
            let floor = this.add.rectangle(0, config.height, config.width, 10, 0xffffff)
                .setOrigin(0,1);
            
            this.physics.add.existing(floor, true);
            
            this.physics.add.collider(player, floor);
            
            this.keys = {
                ...this.input.keyboard.addKeys("W,A,S,D"),
                ...this.input.keyboard.createCursorKeys()
            };
        }
    
        update() {
            let speed = 150;
            this.player.setVelocityX(0);
            if (this.keys.A.isDown || this.keys.left.isDown) {
                this.player.setVelocityX(-speed);
            } else if (this.keys.D.isDown || this.keys.right.isDown) {
                this.player.setVelocityX(speed);
            }
    
            if (  this.player.touching.down &&(this.keys.W.isDown || this.keys.up.isDown)) {
                this.player.setVelocityY(-speed);
            } 
        }
    }
    
    class FirstScene extends PlayerScene {
        constructor() {
            super('FirstScene');
        }
    
        create() {
            super.create();
            this.add.text(10, 10, 'Scene 1\nUse WASD to move the "player"')
                .setOrigin(0)
                
            this.add.line(0, 0, 400, 0, 400, config.height, 0xffffff)
                .setOrigin(0);
        }
        
        update(){
            super.update();
            if(this.player.x > 400){
                this.scene.switch('SecondScene');
                this.player.x -= 30;
            }
        }
    }
    
    class SecondScene extends PlayerScene {
        constructor() {
            super('SecondScene');
        }
    
        create() {
            super.create();
            this.add.text(10, 10, 'Scene 2\nUse WASD to move the "player"')
                .setOrigin(0);
                
            this.add.line(0, 0, 10, 0, 10, config.height, 0xffffff)
                .setOrigin(0);
           
            this.player.x = 30;
        }
        
        update(){
            super.update();
            if(this.player.x < 10 ){
                this.player.x += 30;
                this.scene.switch('FirstScene');
            }
        }
    }
    
    var config = {
        width: 536,
        height: 183,
        physics: { default: 'arcade', 
            arcade: {
                debug: true,
                gravity: { y: 300 }
            }
        },
        scene: [FirstScene, SecondScene]
    };
    
    new Phaser.Game(config);
    <script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>