Adele
Adele

Reputation: 321

How to get access to variables from another scene Phaser 3

I'm trying to create upgrades for my player. I have the player stats in game.js (for example let player_speed = 300).

I've created another scene that contains the UI of the upgrades like so:

upgradeScene.js

import IncreaseSpeed from './Upgrades/increase_speed.js';
import IncreaseDamage from './Upgrades/increase_damage.js';
import IncreaseFireRate from './Upgrades/increase_firerate.js';
export default class Upgrade extends Phaser.Scene {
    constructor() {
        super('upgradeScene');
    }

    preload() {

        this.load.image('bg', 'Assets/UI/bg.png');

    }

    create() {

        const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
        const screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 2;

        bg = this.add.image(screenCenterX, screenCenterY, 'bg').setAlpha(0.5);

        title = this.add.text(screenCenterX, screenCenterY - 300, 'UPGRADES', {
            fontFamily: 'dogicaPixel',
            fontSize: '40px',
            align: 'center'
        }).setOrigin(0.5);

        p = this.add.text(screenCenterX, screenCenterY - 260, 'lorem ipsum dolor sit amet', {
            fontFamily: 'dogicaPixel',
            fontSize: '15px',
            align: 'center'
        }).setOrigin(0.5);
        
        this.scene.add(this, IncreaseSpeed, true);
        this.scene.add(this, IncreaseDamage, true);
        this.scene.add(this, IncreaseFireRate, true);

Increase_speed.js

export default class IncreaseSpeed extends Phaser.Scene {
    constructor() {
        super('increase_speed');
    }

    preload() {
        this.load.image('cardbg', './Assets/UI/cardbg.png');
    }

    create() {

        const screenCenterX = this.cameras.main.worldView.x + this.cameras.main.width / 2;
        const screenCenterY = this.cameras.main.worldView.y + this.cameras.main.height / 2;

        rectC = this.add.image(0, 0, 'cardbg');

        increase_speed_title = this.add.text(0, -100, 'Increase\nSpeed', {
            fontFamily: 'dogicaPixel',
            fontSize: '20px',
            align: 'center'
        }).setOrigin(0.5);

        increase_speed_description = this.add.text(0, 0, 'Lorem ipsum\ndolor sit amet', {
            fontFamily: 'dogicaPixel',
            fontSize: '15px',
            align: 'center'
        }).setOrigin(0.5);

        increase_speed_btn = this.add.text(0, 120, 'UPGRADE', {
            fontFamily: 'dogicaPixel',
            fontSize: '20px',
            align: 'center'
        }).setOrigin(0.5).setInteractive();

        cardC = this.add.container(screenCenterX, screenCenterY, [rectC, increase_speed_title, increase_speed_description, increase_speed_btn]);

        // increase_speed_btn.on('pointerdown', () => {
        //     console.log('test');
        // });
    }

    update() {
        increase_speed_btn.on('pointerover', function (pointer) {
            increase_speed_btn.setScale(1.5);
        })

        increase_speed_btn.on('pointerout', function (pointer) {
            increase_speed_btn.setScale(1);
        })
    }
}

I would like to increase the player_speed when you click on the button in order to set the upgrade.

I'm still learning, I've done research about that but I'm confused cause I haven't find a way to 'communicate' between scenes.

Upvotes: 1

Views: 1714

Answers (1)

winner_joiner
winner_joiner

Reputation: 14820

You can communicate between scene with the Phaser EventEmitters (link to Documentation). You just have to emit and listen(on) on the same Emitter.
In this case, after adding the scene, you get the correct Emitter, with this.scene.get(...).events.

Here a small working demo:
(Just click the red "Click me" text)

document.body.style = 'margin:0;';

class Scene2 extends Phaser.Scene {
  constructor(){
      super('scene2');
  }
  
  create() {
    this.add.text(10, 40, 'SCEEN-SPEED', {color: '#ff0000'}).setOrigin(0);
    
    let button = this.add.text(10, 70, 'CLICK ME => 100 SPEED', {color: '#ff0000', fontStyle: 'bold'})
      .setOrigin(0)
      .setInteractive()
      .on('pointerdown', () => this.events.emit('speed-increase', 100));
  }
}

var config = {
    type: Phaser.AUTO,
    width: 536,
    height: 183,
    scene: {
      key: 'scene1',
      create,
      update
    },
    banner: false
}; 

function create () {
    this.playerSpeed = 0;
    this.playerSpeedText = this.add.text(10, 10, '', { color: '#ffffff'}).setOrigin(0);
    
    this.scene.add(this, Scene2, true);
    this.scene.get('scene2').events.on('speed-increase', speed => this.playerSpeed = speed);
}

function update(){
  this.playerSpeedText.setText(`Player Speed: ${this.playerSpeed}`);
  if(this.playerSpeed > 99){
    this.playerSpeedText.setColor('#00ff00');
  }
}

new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>

Update:
If I understand this correct you have:

  • "gameScene" that adds a "upgradeScene".
  • and the "upgradeScene" adds several specific Scenes like "increaseSpeedScene" and so on

If this is the case, this makes the things abit more complex, but still possible.

you won't need to import anything else (I think), just add the following code in the specific files.

In the "gameScene", in the create function (or after the adding of the UpgradeScene), add:

 this.scene.get('Upgrade-Scene-Key')
     .events.on('upgrade-action', speed => this.playerSpeed = speed);

In the "UpdatedScene" in the create function (or after the adding the specific Scenes) add:

 // this you could do for all upgrade options
 this.scene.get('IncreaseSpeed-Scene-key')
     .events.on('upgrade-speed', speed => this.events
    .emit('upgrade-action', speed));

And in the "IncreaseSpeedScene", just add the emit function call to the button event callback:

// just be sure that the context of this = the current scene
this.events.emit('upgrade-speed', 100)

With other words, you have now one extra event emitter(in the UpgradeScene), that just passes the Event and the Data to the gameScene.

I hope this clears things up abit.

btw.: the names of the event 'upgrade-action', 'upgrade-speed', ... can be choose more or less freely, they just have to match between emiter (emit function) and listener (on function)

Upvotes: 1

Related Questions