Maras Posted July 10, 2014 Share Posted July 10, 2014 Can you please take a look at this code and explain to me what is wrong? From what I know, it should work.. Or at least calling a function from create() could work :-) Thank you!/// <reference path="phaser/phaser.d.ts" />class SimpleGame { logo: Phaser.Sprite; game: Phaser.Game; constructor() { this.game = new Phaser.Game(800, 600, Phaser.AUTO, 'content', { preload: this.preload, create: this.create, update: this.update }); console.log("BEFORE"); this.titleClicked(); console.log("after"); //this.animateLogo(); // >>> Uncaught TypeError: Cannot read property 'scale' of undefined } preload() { this.game.load.image('logo', 'assets/images/phaser2.png'); } titleClicked(){ console.log("CLICKED"); this.titleClicked2(); } titleClicked2(){ console.log("CLICKED 2"); } create() { this.logo = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY, 'logo'); this.logo.anchor.setTo(0.5,0.5); console.log("CREATED"); // this.titleClicked(); // >>> Uncaught TypeError: undefined is not a function // this.logo.events.onInputDown.add(this.titleClicked, this); // >>> Uncaught TypeError: Cannot read property 'add' of null //this.animateLogo(); // >>> Uncaught TypeError: undefined is not a function } update() { } animateLogo(){ this.logo.scale.setTo(0.5,0.5); var logoTween = this.game.add.tween(this.logo.scale); logoTween.to({ x: 1, y: 1 }, 2000, Phaser.Easing.Bounce.Out, true); }}window.onload = () => { var game = new SimpleGame();}; Link to comment Share on other sites More sharing options...
kuuuurija Posted July 10, 2014 Share Posted July 10, 2014 I am not familiar with Phaser, but was interested in this because of TypeScript.I think you need to bind create, preload and update method. Try if this works..constructor() {this.mapBinds();this.game = new Phaser.Game .... // your code}mapBinds() {this.preload = this.preload.bind(this);this.create = this.create.bind(this);this.update = this.update.bind(this);} Maras 1 Link to comment Share on other sites More sharing options...
Maras Posted July 10, 2014 Author Share Posted July 10, 2014 Thanks, it works for this.titleClicked() and this.animateLogo() in create(). It does not work for this though:// this.logo.events.onInputDown.add(this.titleClicked, this);// >>> Uncaught TypeError: Cannot read property 'add' of nullWhich is I guess question for someone familiar with Phaser :-) And why do I need to use the bind method? I never saw it in any tutorial. Thanks! Link to comment Share on other sites More sharing options...
kuuuurija Posted July 10, 2014 Share Posted July 10, 2014 In constructor you are passing create, preload, update methods... because of it "this" operator becomes locked down within the methods.So, create method has no idea what this.animateLogo() method is, to avoid this we bind create method to SimpleGame class.You can find more info here, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind Also you can check this project for TypeScript code help https://github.com/goldenratio/candy-jump-saga/ (uses Pixi.js) Link to comment Share on other sites More sharing options...
playtwice Posted July 10, 2014 Share Posted July 10, 2014 "this" when the state methods are called is the game object itself as it's the one who calls those methods. Couldn't get phaser to work with a default object with the state functions within it, but it worked fine when creating a new state class: export class SimpleGame extends Phaser.Game { constructor() { super( 800, 600, Phaser.AUTO ); this.state.add( 'default', SimpleState, true ); } } export class SimpleState extends Phaser.State { logo: Phaser.Sprite; preload() { this.game.load.image( 'logo', 'assets/images/phaser2.png' ); } titleClicked() { alert( "works!" ); } create() { this.logo = this.game.add.sprite( this.game.world.centerX, this.game.world.centerY, 'logo' ); this.logo.anchor.setTo( 0.5, 0.5 ); this.logo.inputEnabled = true; this.logo.events.onInputDown.add( this.titleClicked, this ); this.animateLogo(); } update() { this.logo.x += 0.5; } animateLogo() { this.logo.scale.setTo( 0.5, 0.5 ); var logoTween = this.game.add.tween( this.logo.scale ); logoTween.to( { x: 1, y: 1 }, 2000, Phaser.Easing.Bounce.Out, true ); } } Maras 1 Link to comment Share on other sites More sharing options...
Maras Posted July 11, 2014 Author Share Posted July 11, 2014 Thanks a lot to both of you guys, using classes which extends Phaser.State solved it and more importantly now I understand whats going on. :-) Link to comment Share on other sites More sharing options...
Maras Posted July 11, 2014 Author Share Posted July 11, 2014 Oh one more thing - I do not understand why animateLogo() does not work in my original source code (Uncaught TypeError: Cannot read property 'scale' of undefined).. I thought that it have reference to the logo, so it should be able to work with it (and create function just update it with actual image, before I want to animate it). I am obviously wrong, but can someone explain to me why? Thank you! Link to comment Share on other sites More sharing options...
clark Posted July 11, 2014 Share Posted July 11, 2014 Are you referring to the constructor? If so, the logo has not been created yet as only the state has been instantiated at that point. Also I feel that your Create() tests should work after your changes now that you are back on the Class scope. (Before, with your object {create: this.create} in Constructor, the create: this.create meant that "this" was the object being passed and NOT the class instance). To get rid of Binding, look at Fat Arrow syntax. Here is my question on StackOverflow http://stackoverflow.com/questions/16157839/typescript-this-inside-a-class-methodThose are cool. Basically saying "take (this) context " and make "this" => that....A good example is this: window.addEventListener("resize", this.onResize);private onResize = (event: Event): void => { console.log("onresize"); clearTimeout(this._resizeTimeout); this._resizeTimeout = setTimeout(this.doResize, this._resizeTimeoutMS);}Window is the one dispatching the event, meaning that "this" refers to the Window, and there is no window.onResize() so you get an error to say that onResize() is not defined.But with a fat arrow, you take the event dispatched by Window and transfer it back to the correct onResize(). Link to comment Share on other sites More sharing options...
Maras Posted July 11, 2014 Author Share Posted July 11, 2014 Edit: (deleted old post asking about setTimeout) Oh so in the end I will have to use A LOT of .bind(this) / fat arrows right? For example setTimeout(this.animateLogo.bind(this), 1000); fixes my problem. Thank you for your patience :-) Link to comment Share on other sites More sharing options...
Recommended Posts