Phaser3 + ES6 classes : how to keep the scope from create to update

I’m a beginner in Phaser 3 dev and I’m trying to define a good pattern for all my games. I found a lot of excellent one-page tutorials but when I translate them in the ES6 classes system, I’m having a hard time with scope issue (elements defined in create() aren’t visible in update).

I’ve seen that one common pattern without ES6 classes is to add the methods in the scene property of the game config object like this :

scene: {
    preload: preload,
    create: create,
    update : update
}

Now here’s my question. If I have this code :

window.onload = function() {
    const config = {
        width: 1136,
        height: 640,
        backgroundColor: "#ECF0F1",
        scene: bootGame
    }
    jeu = new Phaser.Game(config);

    class bootGame extends Phaser.Scene{
        constructor(){
            super("BootGame");
        }
        preload(){}
        create(){    
            let cursors = this.input.keyboard.createCursorKeys();
        }
        update(){
            if (cursors.left.isDown){// cursors not defined}
        }
     }

What should I write to get “cursors” to be defined in update() ?

Many thanks for your help!

I think you could create Cursors as :
-a global variable
-a member of bootGame that you declare in constructor

1 Like
class bootGame extends Phaser.Scene{
        cursors
        constructor(){
            super("BootGame");
        }
        preload(){}
        create(){    
            this.cursors = this.input.keyboard.createCursorKeys();
        }
        update(){
            if (this.cursors.left.isDown){ }
        }
     }
1 Like

Great! Many thanks for your help.
My code works without the “cursors” declaration in the class though (looks like adding “this” everywhere fixes the issue).

the best way to understand the keyword this is that it is a reference to the current object of the class.

when you make a class with any language, you instantiate a new instance of it, and if there are any calls to this, it is referencing the instance itself. this is also why you can’t ever reassign this to something else as it would effectively destroy the reference in memory. You can store a reference to this however, and use it while working inside of another object of another class. doing so changes the current context of this. an example:

var self = this

with that said, given that this is a reference to the entire instance, it is therefore global while working inside of a class, and allows you to be able to utilize it anywhere inside the class itself just as you are doing in your example. it is also how you can create mutators that change and manipulate internal state depending upon what the class needs to do.

if you reference this outside of your game object, you’ll find that since the context scope has changed, so has this. in javascript used in the browser, it will be the window. in node, it will be module.exports

1 Like

Thank you very much for this inspiring answer Aylictal. It’s way more clear right now!

this is a difficult concept to grasp if you have no prior language use but it was incredibly usefull in C/C++ where it was referencing direct memory addresses as opposed to java/javascript/smalltalk virtualized memory. the other more modern languages effectively copied the trend because of its usefulness towards OOP.

it is even more of a difficult concept to use in c++ because of keyword monikers and types. if a class (or a class method) is labeled as static or abstract or interface, using the this keyword will throw a compile error. luckily in JS, the concept of a static class does not exist so it is one less thing you need to worry about, but if you are using typescript, i believe it will work the same way where you will get a runtime error (i’m not very well versed in typescript, but here is an example i believe that would throw an error and it surely would in c++)

export abstract class MyClass {         
    public static myProp = "Hello";

    public static doSomething(): string {
      return this.myProp //should throw an error
      return Myclass.myprop //should be the correct way to handle this in TS
    }
}

const okay = MyClass.doSomething();

edit: I am actually wrong that it doesn’t exist in JS. did some research of my own but I believe they added some of this in es6+:

I was correct in assuming though that nonstatic methods cannot call static traits directly with the this keyword. From the article:

Static methods are not directly accessible using the this keyword from non-static methods. You need to call them using the class name: CLASSNAME.STATIC_METHOD_NAME() or by calling the method as a property of the constructor : this.constructor.STATIC_METHOD_NAME() .

1 Like

Yes, exactly. ES6 change a lot of practices. It’s for the good, but not so easy to mix when learning a framework. Many thanks for your precious precisions!