Home > Enterprise >  Phaser 3: Updating scene variable inside ajax response
Phaser 3: Updating scene variable inside ajax response

Time:09-21

Im trying to update a variable inside the response of an ajax request to see if the token the user passed is true or not.

Below is the full scene code:

class InitScene extends Phaser.Scene{

    constructor(){
        super("InitScene")
    }

    preload(){
        this.Token = getParameterByName('Token')||1;
        let validateData ={
            Token:this.Token
        }
        this.correctToken=false;
        $.ajax({
            url: "validateTokenAPI",
            type: "POST",
            data: JSON.stringify(validateData),
            headers: {
                "Content-Type": "application/json"
            },
            success: function (response) {
                // response is a bool
                this.correctToken = response;
                console.log(this.correctToken);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.log('error');
            }
        });
    }

    create(){

        let { width, height } = this.sys.game.canvas;
        this.add.text(width/2, height/2,"LOADING...", {font: "28px Arial", fill: "black"}).setOrigin(0.5);

        console.log(this.correctToken);
        if(this.correctToken){
            this.scene.start("NextScene");
        } 
    }

    update(){
        console.log(this.correctToken);
        if(this.correctToken){
            this.scene.start("NextScene");
        } 
    }
}



function getParameterByName(name, url = window.location.href) {
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]'   name   '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\ /g, ' '));
}

Im trying to get the result of the ajax inside the preload function and then use it inside the create or update.

The function getParameterByName is simply plagiarized to get the Token from the url;

The preload function sets the value of this.correctToken to false initially then sets it to true if the ajax response is true;

The create and update function move the player to the next scene if the Token is correct (I tried both as I thought maybe its due to the async nature of ajax?)

The value of this.correctToken always prints out as false inside the create and update but is true inside the ajax response

This is not working as I guess the ajax is asynchronous and the value is set in the preload before the response id returned??

I similarly tried putting the ajax in the create and then using it in the update.

Also adding the ajax in a function and then returning the response did not work.

makeValidateAjax(Token){

    let validateData ={
        Token:Token
    }
    $.ajax({
        url: "validateTokenAPI",
        type: "POST",
        data: JSON.stringify(validateData),
        headers: {
            "Content-Type": "application/json"
        },
        success: function (response) {
            return response;
        },
        error: function(jqXHR, textStatus, errorThrown) {
            return false;
        }
    });
}

Edit Also Calling the this.scene.start("NextScene"); inside the ajax response doesnt work because the scene is not defined inside the ajax...

Edit 2

#correctToken;

constructor(){
    super("InitScene")
    this.#correctToken=false;
}

Also defining the variable in the constructor returns an error when I change it in the ajax response

Uncaught TypeError: Cannot write private member #correctToken to an object whose class did not declare it

CodePudding user response:

Consider using an EventEmitter. It could be something along these lines with a singleton pattern:

// eventDispatcher.js
export default class EventDispatcher extends Phaser.Events.EventEmitter {
  constructor() {
    super();
  }
  static getInstance() {
    if (instance === null) {
        instance = new EventDispatcher();
    }
    return instance;
  }
}

    // InitScene's preload

    this.emitter = EventDispatcher.getInstance();

    // use fat arrow functions to preserve the .this in the ajax's callback
    [...]
    success: (response) => {
      // response is a bool
      this.correctToken = response;
      console.log(this.correctToken);
      this.emitter.emit('CORRECT_TOKEN', this.correctToken);
    },
    [...]

    // create
    this.emitter.on('CORRECT_TOKEN', (token) => {
        this.scene.start("NextScene");
    });

As an alternative if you can bother installing one of Rex's plugins (they're all pretty great) I'd go for Await loader.

I'm mocking up some of the main code, untested (you'll need to set it up like the doc page says). Full standalone example on github

const callback = function(successCallback, failureCallback) {
  $.ajax({
    url: "validateTokenAPI",
    type: "POST",
    data: JSON.stringify(validateData),
    headers: {
      "Content-Type": "application/json"
    },
    success: (response) => {
      // response is a bool
      this.correctToken = response;
      console.log(this.correctToken);
      successCallback(); 
    },
    error: (jqXHR, textStatus, errorThrown) => {
      console.log('error');
      failureCallback();
    }
  });
}
this.load.rexAwait(callback);

  • Related