BdR Posted May 31, 2016 Share Posted May 31, 2016 I'm working on a Phaser game but I'm running into some sort of scoping issue and I don't know how to solve it (also posted on stackoverflow btw) When the player wins a ResultPanel appears with the score and some buttons. The player can press the buttons to go to the next level or reset etc. The code to handle back/reset/next is in prototype functions, but those aren't yet defined when the constructor is called(?). At is it now, the function doBtnBack is never called when I press the button. What am I doing wrong? What's the right way to do this? // level complete panel constructor ResultPanel = function(game, stars) { this.game = game; // display how many yellow stars var star1 = stars > 0 ? 'star_yellow' : 'star_grey'; var star2 = stars > 1 ? 'star_yellow' : 'star_grey'; var star3 = stars > 2 ? 'star_yellow' : 'star_grey'; // add text and stars this._panelCaption = this.game.add.bitmapText(144, 12, 'bigrigsfont', 'you are winner!', 48); this._panelStar1 = this.game.add.sprite(300-160, 144, 'buttonicon', star1); this._panelStar2 = this.game.add.sprite(300, 144, 'buttonicon', star2); this._panelStar3 = this.game.add.sprite(300+160, 144, 'buttonicon', star3); // add button icons // NOTE: below code runs but something is wrong because // this.doBtnBack this.doBtnReset etc. is undefined this.btnBack = this.game.add.button(300-100, 300, 'buttonicon', this.doBtnBack, this, 'back_grey', 'back_hl'); this.btnReset = this.game.add.button(300, 300, 'buttonicon', this.doBtnReset, this, 'reset_grey', 'reset_hl'); this.btnNext = this.game.add.button(300+100, 300, 'buttonicon', this.doBtnNext, this, 'next_grey', 'next_hl'); }; ResultPanel.prototype.doBtnBack = function() { console.log('Panel button BACK pressed') // never reaches here }; ResultPanel.prototype.doBtnReset = function() { console.log('Panel button RESET pressed'); }; ResultPanel.prototype.doBtnNext = function() { console.log('Panel button NEXT pressed'); }; I also tried this, but that gives an error Uncaught TypeError: this.doBtnBack is not a function this.btnBack = this.game.add.button(300-100, 300, 'buttonicon', function(){this.doBtnBack();}, this, 4, 0, 8); Link to comment Share on other sites More sharing options...
rich Posted May 31, 2016 Share Posted May 31, 2016 Why are you defining those functions on the prototype? Link to comment Share on other sites More sharing options...
LTNGames Posted May 31, 2016 Share Posted May 31, 2016 I've never tested it but I'm pretty sure when calling a function you need the parenthesis at the end, . so.... this.doBtnBack() this.btnBack = this.game.add.button(300-100, 300, 'buttonicon', this.doBtnBack(), this, 'back_grey', 'back_hl'); this.btnReset = this.game.add.button(300, 300, 'buttonicon', this.doBtnReset(), this, 'reset_grey', 'reset_hl'); this.btnNext = this.game.add.button(300+100, 300, 'buttonicon', this.doBtnNext(), this, 'next_grey', 'next_hl'); Link to comment Share on other sites More sharing options...
drhayes Posted May 31, 2016 Share Posted May 31, 2016 Are you calling ResultPanel without using new, i.e. "var panel = ResultPanel();"? What does "console.log(this.doBtnReset);" say when you add it at the top of the ResultPanel constructor? Is this all the code? You're not reassigning the prototype somewhere else, like "ResultPanel.prototype = {}"? Link to comment Share on other sites More sharing options...
rich Posted May 31, 2016 Share Posted May 31, 2016 4 hours ago, LTNGames said: I've never tested it but I'm pretty sure when calling a function you need the parenthesis at the end, . so.... this.doBtnBack() this.btnBack = this.game.add.button(300-100, 300, 'buttonicon', this.doBtnBack(), this, 'back_grey', 'back_hl'); this.btnReset = this.game.add.button(300, 300, 'buttonicon', this.doBtnReset(), this, 'reset_grey', 'reset_hl'); this.btnNext = this.game.add.button(300+100, 300, 'buttonicon', this.doBtnNext(), this, 'next_grey', 'next_hl'); Not in this case, no, otherwise it would insert the result of doBtnBack into the Button, as it's invoking it immediately when the () are included. LTNGames 1 Link to comment Share on other sites More sharing options...
LTNGames Posted May 31, 2016 Share Posted May 31, 2016 Ah, okay. Still new to Phaser and JS but watching what everyone has to say on these forums is helping out a lot, thanks for letting me know. I'm assuming that argument is a callback for when the button is pressed? Link to comment Share on other sites More sharing options...
rich Posted May 31, 2016 Share Posted May 31, 2016 Correct, in the example above you're inserting a reference to the function. So when the callback is invoked the function itself is called. If you were to put () there it would invoke the function immediately, and store the result of that function as the reference (which is perfectly valid in some cases, where a function returns another function, but not in this one) LTNGames 1 Link to comment Share on other sites More sharing options...
BdR Posted May 31, 2016 Author Share Posted May 31, 2016 Okay, I actually use a MyGame prefix/namespace on all my objects, because that's also used in this code example. I admit I don't quite know what that the MyGame. does precisely. So my code actually looks more like this: var MyGame = {}; MyGame.Bootup = function() { //etc. MyGame.GameState = function() { create: function() { var panel = new MyGame.ResultPanel(this, 3); } }; And see the panel object code below. Now, if I remove all the MyGame. from the code below but keep it in the code above (except in the var panel = new ResultPanel(this, 3)" then it works(?). No clue why that is. // level complete panel constructor MyGame.ResultPanel = function(game, stars) { this.game = game; // etc. }; MyGame.ResultPanel.prototype.doBtnBack = function() { console.log('Panel button BACK pressed') // never reaches here }; MyGame.ResultPanel.prototype.doBtnReset = function() { console.log('Panel button RESET pressed'); }; MyGame.ResultPanel.prototype.doBtnNext = function() { console.log('Panel button NEXT pressed'); }; // level complete panel constructor MyGame.GameState = function() { create: function() { var panel = new MyGame.ResultPanel(this, 3); } }; but it works Link to comment Share on other sites More sharing options...
LTNGames Posted May 31, 2016 Share Posted May 31, 2016 1 hour ago, BdR said: I don't quite know what that the MyGame. does precisely. MyGame, is a namespace, it will store everything inside of it so it stops you from polluting the global space. If you run a console.log(MyGame); the console will show everything that is inside of it. That being said I still have no clue why you can't call this.doBtnBack from within the main function. Link to comment Share on other sites More sharing options...
Recommended Posts