Best practice for "composite" game objects?

This appears to do exactly what I want:

  1. custom Plane class extends Container; its constructor creates all the little sub-pieces: physics sprites, text, shapes, etc.
  2. when you extend Container, Phaser seems to require that you also define a preUpdate(time, delta) method on your subclass; in that method, I explicitly update the positions of each of the sub-pieces by re-assigning into their x & y coords

it-flies-rightward

Like so:

export default class Plane extends Phaser.GameObjects.Container {

  constructor( scene, x, y, name, size ) {
    super(scene)

    this.vIcon = scene.physics.add.sprite(x, y, 'airplane')
    this.vLabel = scene.add.text(x, y + 15, name, TextStyle.PlaneName)
    this.vLabel.setOrigin(0.5)

    scene.add.existing(this)
  }


  fly() {
    this.vIcon.setVelocity(10, 0)
  }

  preUpdate = (time, delta) => {
    this.vLabel.x = this.vIcon.x
    this.vLabel.y = this.vIcon.y + 15
  }

}

A couple notes:

  • Updating the coords in preUpdate is simply a matter of re-running the same calculation that the constructor uses to position the item in the first place. If it really bothers you to copy/paste that math in two places, you could refactor the position calculations into private functions within the same module. Or you could probably not bother to set the position in the constructor at all, and just rely on math in preUpdate to set their positions on the next frame draw. That might result in a brief initial flash of glitchy layout, depending on how the lifecycle plays out.

  • I’ve seen elsewhere that folks call super.preUpdate within their custom class’s preUpdate method, but it throws when I try that (Phaser v3.54). So I just do the position assignment.

Frankly, I think it’s great. I feel like I’m making Phaser do almost all the work here.