Please I need any help with Custom Player class

Hi guys :wave:

Could anyone please help me :pray:

Maybe my question is stupid, but I have already spent a lot of time on it.

Pre-condition: I have a client on Phaser3 with arcade physics and Matter.js on server side, this is a multiplayer game. All physics are calculated on server side, and client should only represent server-side state. Player itself is a circle with particles and a label over it with user name.

Question: What is the most suitable base class for Player ? Previously I had some experience in Unity and there I would take just a GameObject and put inside everything I need, but here I don’t understand how to combine Phaser.GameObjects.Graphics, Phaser.GameObjects.Text and Phaser.GameObjects.Particles.ParticleEmitter in a single class

Also, if I need only to represent player position from server state I don’t need client physics, so what is the best way to move player smooth?

Please, could anyone share some knoledge :pray::pray::pray:

Hi @sedoyjan, welcome to the forum :grin:

Not a stupid question at all, as there are a lot of ways you could handle this. Here are a couple things you could try:

Extend Graphics - As you noted in your post, all of the parts of your player are extended from GameObject, so they’ll all have access to the same GameObject methods. However, probably only one of these will have a physics body enabled, and I’m guessing that’s a circle drawn from the Graphics object. In that case, I would extend Phaser.GameObjects.Graphics to a custom subclass - let’s call it Player. You can enable a body for this object from within the Player class, and you can also create your text and particles and store them to properties on the Player instance.

It’s up to you to keep them all in sync - you’ll need to update the positions of your text and particles to match the “parent” graphics object in the new Player class’s update method, and you’ll need to CALL Player’s update method yourself within the update method of your scene. If the Player has physics interactions, make sure you update the positions of the text and particles in relation to the BODY’s x and y, not the Graphics object, otherwise they’ll appear to lag a frame behind.

So in a way, you’d kind of be duplicating the setup you had in Unity. You can access the text and particles of a player through whatever properties you set them to. But while the player class has REFERENCES to these objects, they’re all in the same update list for your scene, so if your player gets destroyed, you need to remember to destroy the text and particles as well!

Container - Another option is Phaser.GameObject.Container. It’s been criticized for performance reasons that I don’t fully understand, but it’s an extension of GameObject that can have other GameObjects added to it, and it applies any transformations you apply on the container to its children GameObjects. I’ve found containers to be very convenient for bundling game objects together to make one single entity, so this might be a convenient option. I’ll leave it to those who understand them better to point out their potential flaws.

Other Stuff - There’s some other weirdly specific stuff like the “follow” and “source” properties on particle emitters that you could use in conjunction with either of the above. Just go to the GameObject > Particle Emitter section of the Phaser 3 Examples and you may find some convenient features.


As for the networking, I’m afraid that’s beyond me. But if you need any more help getting a Player class up and running, let me know and I’ll dig up some relevant examples from the Phaser 3 labs.

2 Likes

You won’t mash all the classes together.

One methods is not to extend anything, just make a simple class that aggregates all the game objects:

class Player {
  constructor(scene, x, y, name, particleManager) {
    this.circle = scene.add.circle(x, y, RADIUS, FILL_COLOR).setDepth(1);
    this.label = scene.add.text(x, y, name).setDepth(2);
    this.emitter = particleManager.createEmitter().startFollow(this.circle);
  }

  // update() should be called manually somehow
  update() {
    this.label.setPosition(this.circle.x, this.circle.y);
  }
}

function create() {
  const player1 = new Player(this, 0, 0, 'Player 1', particleManager);
}

The other is to extend the main game object and host the others. I used Arc but you could use Graphics.

class Player extends Phaser.GameObjects.Arc {
  constructor(scene, x, y, name, particleManager) {
    super(scene, x, y, RADIUS, 0, 360, false, FILL_COLOR);
    this.setDepth(1);
    this.label = scene.add.text(x, y, name).setDepth(2);
    this.emitter = particleManager.createEmitter().startFollow(this);
  }

  // update() should be called somehow
  update() {
    this.label.setPosition(this.x, this.y);
  }
}

function create() {
  const player1 = this.add.existing(new Player(this, 0, 0, 'Player 1', particleManager));
}

You could use Container but it’s not really necessary just to pin the label on the circle.

3 Likes

Thanks a lot :slightly_smiling_face: :pray: