Matter and TypeScript

I’m hoping someone can help me out here - I’m an experienced C++ game developer, but new to web development, JavaScript, Phaser, TypeScript, etc…

TypeScript will transpile this code with no problems:

let sprite:Phaser.Physics.Matter.Sprite = this.matter.add.sprite(200, 50, 'image');
let speed:number = MatterJS.Vector.magnitude(sprite.body.velocity);
console.log(speed);

But when run it I get this error:
Uncaught ReferenceError: MatterJS is not defined

So TypeScript knows what MatterJS is, but JavaScript doesn’t.

Is this a configuration issue on my end? Something to do with how Phaser integrates with Matter?

From what I have been able to figure out, JavaScript wants to see something like this:
Phaser.Physics.Matter.Matter.Vector.magnitude
rather than
MatterJS.Vector.magnitude

This is just one example of the problem, I had the exact same issue when trying to use MatterJS.Vertices.centre… So I imagine the problem is going to keep coming up.

I have some really vague notions of what could be going on, but I don’t understand enough about how all these technologies work to figure out more than that right now. Would appreciate some advice… Maybe this TypeScript code snipped works fine for others and I have just configured my project incorrectly. I’m using VSCode and webpack. Thank you!

That’s a Phaser bug, should be fixed since v3.22.0.

I’m using the latest stable Phaser 3.24.1.
I guess the bug you’re referring to this issue:

Seems like it might be related to my issue. If I understood how namespaces worked between JavaScript and TypeScript, maybe I could figure it out. If I move everything from matter.d.ts into phaser.d.ts under Phaser.Physics.Matter.Matter - I think I could get it to work - but obviously I shouldn’t have to do that.

Leaving TypeScript out of it for the moment…

This code works in JavaScript:

var velocity = Phaser.Physics.Matter.Matter.Vector.create(4,4);
var speed = Phaser.Physics.Matter.Matter.Vector.magnitude(velocity);
console.log(speed);

But this code does not:

var velocity = MatterJS.Vector.create(4,4);
var speed = MatterJS.Vector.magnitude(velocity);
console.log(speed);

Should it work? Is there an include/import I need to do to make it work?

I don’t think so. I think Phaser’s declaration file is wrong, as there is no MatterJS namespace.

2 Likes

Yeah, I don’t get it. Here is my fix for now - I searched for all instances of “MatterJS” and replaced with “Phaser.Physics.Matter.Matter” in both matter.d.ts and phaser.d.ts

That seems to have fixed the issue. Now I can’t use “MatterJS” for anything, I have to always use “Phaser.Physics.Matter.Matter”. Very verbose, unfortunately, but so far it seems to work as I expect it to.

I wish I understood the issue better, to contribute something.

I think everything under the MatterJS namespace is just for type information. There’s no implementations under that namespace as @samme mentioned.

I believe when in a Scene, this.matter.vector is a reference to https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Matter.MatterPhysics.html#vector__anchor

which is of type MaterJS.VectoryFactory that has the magnitude() method you are using: https://github.com/photonstorm/phaser/blob/master/types/matter.d.ts#L4248

Perhaps there is also another static version of magnitude() and that’s the one you are using via the Phaser.Physics.Matter.Matter namespace? There is this Vector class defined with various statics: https://github.com/photonstorm/phaser/blob/master/types/matter.d.ts#L4007

1 Like

I think you’re right - MatterJS is just for type information. The confusing part as a beginner is that intellisense shows all the static functions, but you can’t actually use them.

And yes, it appears that this.matter.vector works. I’m also using Vertices which similarly is accessible from this.matter.vertices.

So then what I’ve arrived at is to use MatterJS for types - nice and short. Then I set up a global variable MatterJSRef pointing to this.matter so I can use it quickly from anywhere.

So my original code that I wanted to work:
MatterJS.Vector.magnitude(sprite.body.velocity);
becomes:
MatterJSRef.vector.magnitude(sprite.body.velocity);

Those classes, VectorFactory and Vector seem to have identical functions except Vector functions are all static. I think this is generated code that comes from the same place and ends up pointing to same code in JavaScript? So using either will be identical. Again, I don’t understand at all what is happening - but looking at phaser.js - that’s my guess :slight_smile:

1 Like