Jump to content

Simple code, many errors [Webstorm, TypeScript]


Maras
 Share

Recommended Posts

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

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);}
Link to comment
Share on other sites

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 null

Which 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

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

"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 );        }    }
Link to comment
Share on other sites

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

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-method

Those 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

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

 Share

  • Recently Browsing   0 members

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