Jump to content

Refering to THIS in an event


ZoomBox
 Share

Recommended Posts

My problem is simple:

 

I have a class that extends the Sprite class.

In the constructor I have this:

Piece=function(_game, _x, _y) {    this.events.onInputDown.add(        this.init();    );};

The problem is (obviously?) that when I click on an object of the Piece class, "this" doesn't refers to the class but to my index page...

 

I know how to do in plain javascript but it doesn't work in Phaser. Please HELP :(

 

Thank you :)

Link to comment
Share on other sites

Phaser is plain JavaScript, but there are many ways to write JavaScript and each may affect the value of 'this', often in difficult to determine ways.

 

It doesn't look like your syntax is correct as you're trying to call a function inside the add method, rather than pass the function to it (a subtle diffference). Calling functions typically means the function statement ends with () or (parameter, parameter2) etc. When passing the function, you leave off the parentheses.

 

Also, all of the signals Phaser uses for events let you pass a context as the last parameter. At a guess, I'd say try this:

Piece=function(_game, _x, _y) {    this.events.onInputDown.add(this.init, this);};
Link to comment
Share on other sites

add function takes a callback and a callbackContext http://docs.phaser.io/Phaser.Signal.html#add

var callback = function() {     this.init();};this.events.onInputDown.add(callback, this);

Alternatively you can use 'bind' to set the function context yourself.

var callback = function() {    this.init(); };this.events.onInputDown.add(callback.bind(this));
Link to comment
Share on other sites

Oh nice, it works, I was close with my tests...

But I still have a problem (because I simplificated too much the first post):

 

Actually, the callback function I call is in an other object which uses "this" to refer itself. And now, with your solution, in my other object's callback function, "this" refers to the original Piece object...

 

Here is the example:

piecesManager = new PiecesManager();Piece=function(){    this.events.onInputDown.add(piecesManager.init, this);}PiecesManager=function(){}PiecesManager.prototype.init=function(_piece){    console.log(_piece); // perfectly working, refering to the Piece caller    console.log(this);      // not working, refering to the Piece caller too :-(}

(thank you very much for your time)

Link to comment
Share on other sites

@lewster32: It would work I think, but it's not very clean. It doesn't make sense to me to pass the piecesManager as parameter since it's a global variable, I could just use the variable in my class like this:

PiecesManager.prototype.init=function(_piece){    console.log(piecesManager); // it obviously works but seems REALLY strange to use a reference to the pieceManager instead of "this" inside the class itself}

And I still need my piece to be in the arguments (but I could pass them in an Array I know).

 

@eguneys: Thank you for the article but it's quite the same as having a global variable in my case.

 

 

This kind of things will forever be blurry for me I guess :-(

Thank you for your time, for the moment, I use the global variable solution which I find dirty as hell.

Link to comment
Share on other sites

My syntax is slightly different (pretty much equivalent to the syntax that TypeScript outputs) but here's how I'd usually craft an object manager pattern:

var PiecesManager = (function() {   function PiecesManager() {    // constructor    this._pieces = [];  }  PiecesManager.prototype.init = function() {    // instance method - 'this' here always refers to the PiecesManager *instance* created when 'new' is used  };  PiecesManager.doSomething = function() {    // static method - 'this' here always refers to this original object (i.e. PiecesManager itself, the 'class' all instances derive from)  };  PiecesManager.prototype.add = function(piece) {    this._pieces.push(piece);  };  PiecesManager.prototype.alert = function(text) {    alert(text);  };  // factory method to easily allow you to create new pieces in the manager  // essentially the same as how Phaser's factory methods work  PiecesManager.prototype.create = function(x, y) {    var newPiece = new Piece(this, x, y);    this.add(newPiece);    return newPiece;  };  return PiecesManager;})();var Piece = (function() {  function Piece(piecesManager, x, y) {    // constructor    this._piecesManager = piecesManager; // keep a reference to the manager    this._piecesManager.add(this); // add this piece to the provided manager    this.x = x;    this.y = y;  }  // an instance method that calls a function on the manager  Piece.prototype.managerAlert = function(text) {    this._piecesManager.alert(text);  };  return Piece;})();// usagevar piecesManager = new PiecesManager();var piece1 = piecesManager.create(0, 0); // create a new Piece within the manager (easier)piece1.managerAlert("Hello!"); // get the piece to alert the message "Hello!" through its managervar piece2 = new Piece(piecesManager, 10, 10); // instantiate a piece manually (the instance's constructor will ensure it's added to the manager if one is provided)

I find this way of writing JS makes scope easier to think about, and this pattern (the factory pattern) works very well for situations where you have interdependent parent-child relationships, such as in the case of objects and object managers.

Link to comment
Share on other sites

Wow thank you for the explanation.

You couldn't be closer to what I've done at the moment, it ensures me that it's the best way not to be annoyed with scopes problems.

I noticed that Phaser works like that too: Always store a reference to the parent.

 

Thank you very much, it's the most pretty way I found (less dirty ? haha), it's simple and working.

Thank you :-D

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...