Is there an easy way to change context of 'this'

Current Phaser Version : 3.55.2

My issue is that when I am calling the addNewPlayer function from another file client.js the context of this is not what I want. I want the same this as if the function was called from scene-one.js

When I call the addNewPlayer function from the client.js file I am receiving this error. (I have also logged this for each addNewPlayer call)

I have read online that I can use the call() function to specify what the value of this is. However , in scene-one.js if I use Client.askNewPlayer.call(this) there doesn’t seem to be any difference.

is there any easy way to change the context of this , should I even be trying to do that?
Is there a better way that I should be going about this task?

thanks,

Mschilli

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/socket.io/socket.io.js"></script>
    <script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
    <script src="js/scene-one.js" type="text/javascript"></script>
    <script src="js/client.js" type="text/javascript"></script>
    <title>Basic multiplayer online game</title>
</head>
<body>
    <div id='game'></div>   
    <script>
        const phaserConfig = {
            type: Phaser.AUTO,
            parent: "game",
            width: 1280,
            height: 720,
            backgroundColor: "#5DACD8",
            scene: [SceneOne]
        };
        const game = new Phaser.Game(phaserConfig);
    </script>
    
    
</body>
</html>

scene-one.js

class SceneOne extends Phaser.Scene {

    constructor () {
        super('SceneOne');
    }

    init() {
     
    }

    preload() {
        this.load.tilemapTiledJSON('map', 'assets/map/example_map.json');
        this.load.image('tileset' , 'assets/map/tilesheet.png')
        this.load.image('sprite','assets/sprites/sprite.png');
    }

    create(data) {
        this.playerMap = {};
        let map = this.add.tilemap('map');
        map.addTilesetImage('tilesheet', 'tileset'); // tilesheet is the key of the tileset in map's JSON file

        var layer;
        for(var i = 0; i < map.layers.length; i++) {
            layer = map.createLayer(i , map.tilesets[0]);
        }
        
        layer.setInteractive()
        layer.addListener('pointerup' , this.getCoordinates , this)

        this.addNewPlayer(0 , 10 , 30);
        this.addNewPlayer(1 , 10 , 60);
        //Client.askNewPlayer(/*{callbackScope: this}*/).call()
        Client.askNewPlayer()
                                        
    }

    update(time, delta) {
  
    }

    getCoordinates(pointer){
        console.log(`worldX = ${pointer.worldX} , worldY = ${pointer.worldY}`)
    }

    addNewPlayer = function(id,x,y){
        console.log(this)
        this.playerMap[id] = this.add.sprite(x,y,'sprite');
        console.log('addNewPlayer was called')
    };

   
    


}

var sceneOne = new SceneOne

client.js

var Client = {};
Client.socket = io.connect();

Client.askNewPlayer = function(){
    Client.socket.emit('newplayer');
};

Client.socket.on('allplayers',function(data){
    for(var i = 0; i < data.length; i++){
        sceneOne.addNewPlayer(data[i].id,data[i].x,data[i].y);
    }
});

Just a quick addition

in client.js if I used Client.socket.emit.call(this, 'newplayer') I receive the following error. So I can’t use the same this with the .call() function.

universalModuleDefinition:3 Uncaught TypeError: Cannot read properties of undefined (reading 'push')
    at n.emit (universalModuleDefinition:3:1)
    at Client.askNewPlayer (client.js:21:24)
    at SceneOne.create (scene-one.js:45:29)
    at SceneManager.create (phaser.js:100338:26)
    at SceneManager.loadComplete (phaser.js:100250:14)
    at LoaderPlugin.emit (phaser.js:1908:35)
    at LoaderPlugin.loadComplete (phaser.js:196794:14)
    at LoaderPlugin.fileProcessComplete (phaser.js:196760:18)
    at ImageFile.onProcessComplete (phaser.js:4961:21)
    at data.onload (phaser.js:19311:19)

I think it may be the context is correct but that scene hasn’t booted yet.

But the scene was “booted” previously correct? because the first calls to this.addNewPlayer successfully printed the sprite on the screen.

I don’t know why this worked but I moved var sceneOne = new SceneOne from scene-one.js into the index.html file under the phaserConfig object.

I believe in both spots the var sceneOne was a global variable.

I think this scene, sceneOne, was never booted. You passed SceneOne to the game config so a different new SceneOne() would get booted.

Thank you, that second response actually clicked with me. I don’t know how it was kind of working before with my “fix” but I have changed the script element in the index.html file to following.

<script>
        var sceneOne = new SceneOne;

        const phaserConfig = {
            type: Phaser.AUTO,
            parent: "game",
            width: 1280,
            height: 720,
            backgroundColor: "#5DACD8",
            scene: [sceneOne]
        };

        const game = new Phaser.Game(phaserConfig);     
    </script>

I changed the scene in the config to the object I created instead of passing the class. I believe that this is what I want for now, atleast I know that my this context will be the same if another file calls a function from scene-one.js