phaserjs/phaser-ce

Troubles Subclassing Sprite with TypeScript - game is not instance of Phaser.Game

Closed this issue · 15 comments

Hello, having issues subclassing Sprite with TypeScript. From searching and reading documentation it seemed the preferred method was to subclass, instantiate the subclass, then use game.add.existing() to tie it to the game.

Trying to do that but encountering an instanceof error based on the code that seems to have been added to a recent point release. (Phaser.Component.Core.init checks types of the game, x, and y arguments).

For some reason (I'm new to TypeScript), setting a breakpoint in chrome console and issuing the typeof call does return "object" for the Phaser.Game but it is clearly an instance of Phaser.Game

console

From the class extending Phaser.State:

this.game.add.existing(
  new Turret(this.game, x, y));

From the Phaser.Sprite:

export default class Turret extends Phaser.Sprite {

    constructor(game : Phaser.Game, x: number, y: number) {
        super(game, x, y, 'turret');
   }
}

Uncaught Error: The value passed as the game argument ([object Object]) is not an instance of Phaser.Game.
at Turret.Phaser.Component.Core.init (phaser-split.js?2ffb:23760)
at Turret.Phaser.Sprite [as constructor] (phaser-split.js?2ffb:27188)
at new Turret (Turret.ts?348e:7)
at eval (Setup.ts?60fe:43)
at Array.forEach ()
at Setup.create (Setup.ts?60fe:40)
at Phaser.StateManager.loadComplete (phaser.js?b1d1:28696)
at Phaser.StateManager.preUpdate (phaser.js?b1d1:28462)
at Phaser.Game.updateLogic (phaser.js?b1d1:35260)
at Phaser.Game.update (phaser.js?b1d1:35207)
Phaser.Component.Core.init @ phaser-split.js?2ffb:23760
Phaser.Sprite @ phaser-split.js?2ffb:27188
Turret @ Turret.ts?348e:7
(anonymous) @ Setup.ts?60fe:43
Setup.create @ Setup.ts?60fe:40
loadComplete @ phaser.js?b1d1:28696
preUpdate @ phaser.js?b1d1:28462
updateLogic @ phaser.js?b1d1:35260
update @ phaser.js?b1d1:35207
updateRAF @ phaser.js?b1d1:63029
_onLoop @ phaser.js?b1d1:63012

Perhaps I am missing something or doing it wrong. Thanks!

samme commented

Try setting a breakpoint on https://github.com/photonstorm/phaser-ce/blob/v2.8.3/src/gameobjects/components/Core.js#L65 and examining the value of game there.

Still the same. I'm tempted to set skipTypeChecks to true but can't quite figure if that is a property I can set either. Is this something the end user can set?

samme commented

What value does it show in the Scope pane at that breakpoint?

You can set Phaser.Component.Core.skipTypeChecks = false.

Have you already tried out this?

this.turret = new Turret(this.game, x, y);

export default class Turret extends Phaser.Sprite {

    constructor(game : Phaser.Game, x: number, y: number) {
        super(game, x, y, 'turret');

        game.add.existing(this);
   }
}

@samme intriguingly it shows a Phaser.Game

@digitsensitive just so I understand, your suggestion is to still call the same super constructor, then use the call to add an existing sprite? I think the problem is the super constructor, so I never made it to any other lines in the constructor. Just gave it a shot to make sure - and yeah, can't get past the Phaser.Sprite(game, x, y) constructor.

Also TypeScript doesn't like Phaser.Component.Core.skipTypeChecks = true; -

(15,16): error TS2339: Property 'Component' does not exist on type 'typeof Phaser'.

Finally trying Phaser['Component'].Core.skipTypeChecks = true; sidestepped TypeScript and also the type safety of the Sprite constructor and I'm back in business here. But I don't really want to be skipping type checks!

samme commented

It's fine to use skipTypeChecks = true, it's a bit redundant if you're already using TypeScript. It won't affect any of your TypeScript checks.

Indeed Phaser.Component isn't in the definitions at all, sorry about that.

It's still strange that your game argument is failing instanceof Phaser.Game. Are you extending Phaser.Game in any way? All the same, if the game is running fine, it's probably not important.

not sure if it helps you, but have a look at one of my small projects and have a look at my configurations:
https://github.com/digitsensitive/phaser-machine-learning/tree/master/experiments/atari-pong

maybe it would help to send the github link to your project, so I can have a look?

Just chipping in to say that I'm having the exact same issue.

Logging typeof game says that it's just an object, and not Phaser.Game

Used this boilerplate and might have missed something. A helper function that disables the built in type checking seems fine.

samme commented

Logging typeof game says that it's just an object, and not Phaser.Game

That's normal, but try (game instanceof Phaser.Game).

Ah, got it mixed up.

However I found the solution for my setup, I was just importing Phaser the wrong way.

In my project's main file, phaser is imported as import 'phaser' at the top level, and in my Player class I did import * as Phaser from 'phaser-ce', as that's what the IDE suggests. Nothing seemed off in the type suggestions. Doing the former fixes it, stupid mistake to make.

Before game instanceof Phaser.Game returned false, now it's true.

Is this not relevant on your end, @lucasgray?

Ha, that fixed my issue as well. I would be interested to know how the difference in import statement resolves the instanceof issue

samme commented

Property 'Component' does not exist on type 'typeof Phaser'.

Fixed in dc149ab, thanks.

confirm that while I hadnt checked imports and replace all phaser with phaser-ce nothing work. Some joke was in that thing instanceof checking show that this.game was instance of Game.

ps: In my case I didnt use typescript

@lucasgray try to be consistent when importing the phaser library. Probably you're exposing the library twice and using then between your files. As they're objects, they can be equals but they're never from the same memory address.

If you started to import the library from phaser, keep using it between your files and everything is going to be fine.

// they both have the game property
// but they aren't from the same instance.
import Phaser from 'phaser'
import Phaser from 'phaser-ce'

Does it makes sense to you? Let me know if you need help.

i do it in a similar case:
lean/phaser-es6-webpack#64