Scope issue (again)

I created a custom method into a scene class but am not being able to access it. This is my code:

class MyScene extends Phaser.Scene {

    constructor () {
        super({key: "myScene"});
    }
  
    preload() {
        this.load.image('scnMyscene','assets/images/myscene.png');
        this.load.image('btnSound','assets/buttons/btnSound.png');
    }

    create() {
        var scnMyscene = this.add.image(512, 384, "scnMyscene")
        var btnSound = this.add.image(752, 135, "btnSound").setInteractive();

        btnSound.on('pointerup', function (event) {
           this.DoSound(); // won't work
           DoSound(); // won't work either
        });
    }

    DoSound() {
        console.log('do')
    }
}

export default MyScene;

It’s puzzling me because as far as I know in this context this represents the scene itself and so it should work. What’s wrong here?

Also, how can I CLOSE this scene?

Use more logging :slight_smile:

‘this’ will refer to btnSound. If you want to refer to scene, use (event) => { 
 }
DoSound without any prefix means ‘window.DoSound’. That doesn’t exist.

Destroy scene¶

scene.scene.remove(key);
1 Like

Milton, unfortunately two things failed for me


First I tried:

event.DoSound();
Uncaught TypeError: event.DoSound is not a function

event.scene.DoSound();
Uncaught TypeError: Cannot read property ‘test’ of undefined

Also it failed too:

btnClose.on('pointerup', function (event) {
   scene.scene.remove('myScene');
}); 

Any idea?

I meant, use an arrow function :slightly_smiling_face:

change

btnSound.on('pointerup', function (event) {

to

btnSound.on('pointerup', (event) => {
1 Like

Milton, I got it. But in fact it’s driving me crazy! LoL!

When I use the arrow function this will refer to the scene from within the function event, correct? And how I reach the scene from my custom method? See:

create() {
   var btnSound = this.add.image(752, 135, "btnSound").setInteractive();
   btnSound.on('pointerup', (event) => {
      this.DoSound();
   });
}

DoSound() {
   console.log ('DoSound'); // it works!
   btnSound.setVisible(false); // Cannot read property 'setVisible' of undefined
}

You have declared btnSound inside create(). Either make it a class member (this.btnSound), or a global (outside the class).

1 Like

I see!

A final question
 in this case how could I target the object itself without explicitly declare its whole “path”?

For instances I see that it works:

create() {
   this.btnSound = this.add.image(752, 135, "btnSound").setInteractive();
   this.btnSound.on('pointerup', (event) => {
      this.btnSound.setVisible(false);
   });
}

There is a way of target itself inside the function? Or forcing declare the objects as part of the scene I cannot target to self?

I’m not sure I understand the question.
If you use an arrow function, the ‘target’ (this) is not set, and therefore remains the class (scene).
If you use functon() {}, ‘this’ is set to the target, but then you’ll need a reference to the scene. See the solution to your previous post.

1 Like

I think I got it. I always had a certain problem to understand scope, specially with classes. Thanks for all your huge patience and help!

People like you makes all the difference in a day in the life of a coder.

:blush:

There’s no implicit access to properties of this, if that’s what you mean.

this.btnSound and btnSound would be completely different values.

1 Like