Can't modify game objects within Container

Hi All,

I am trying to create a stopwatch component by extending Phaser’s Container class. I ran into a problem while trying to modify properties of individual game objects within the Container.

Specifically, changing an object property (e.g. angle of a dial needle) works as expected when called from the Container’s constructor, but not from the container’s update function, which is triggered within a scene’s update function. In the latter case, the dial needle appears the same, even though its angle property is actually changed when console logged.

Below is a simplified code excerpt:

class Stopwatch extends Phaser.GameObjects.Container {
	
  constructor(sceneObj, x, y) {
    super(sceneObj, x, y)
    ...
    this._addObjects()
  }

  _addObjects() { // called from the container's constructor
    this.objects = {
       stopwatch: this.sceneObj.add.image(0, 0, "stopwatch"),
       dial_needle: this.sceneObj.add.image(0, 0, "dial_needle")
    }
    const { stopwatch, dial_needle } = this.objects
    this.add([stopwatch, dial_needle, this.stopwatchGraphics])

    setTimeout(() => dial_needle.setAngle(70), 4000) // this works!
  }

  update() { // triggered within scene's update function
    ...
    if (currentTimestamp - lastTimestamp > timeDelta) {
      let newAngle = needleAngle + angleDelta * actualTimeDelta

      if (newAngle >= 360) {
        // console log here shows objects with updated properties
        this.emit('stopwatch-done')
        return
      }
      
      this.objects.dial_needle.setAngle(newAngle) 
      // console log here shows that "dial_needle" angle is changed,
      // but this doesn't reflect on the object's appearance on screen
    }
  }
  ...
}

I could perhaps avoid this issue by extending BaseGameScene instead of the Container and using the update function to move all objects in unison if needed, but I am interested in why my current approach fails. I am guessing it might have something to do with Display Lists of Container and Scene, but I hadn’t been able to figure out the exact cause so far.

That should work, see

1 Like

Looks pretty good to me. You have a … in your constructor so I’m not sure if you include this in your original code, but are you setting this.sceneObj = sceneObj in your container’s constructor? That could explain why you’re creating the components of your stopwatch and able to change their values, but you’re not seeing them updating from the scene’s display list. But if that were the case, you’d probably be getting an error on trying to call “add” from an undefined property, so I could be totally off.

Also note that the call to super(sceneObj, x, y) in your container’s constructor, or any constructor that extends a GameObject, will automatically create a reference to the scene at this.scene, so setting a reference to the scene you’ve passed to the constructor would technically be redundant.

1 Like

@samme Delightful example! :smiley:
Thx a lot, I will look further into this and write an update if I figure it out (or just mark as resolved in a day or two).

@StinOfSin Yes, this.sceneObj = sceneObj is set alright, no issues there. Thanks for your tip!

I was able to get back to this after a while and I found what was causing the issue - I was referencing new Stopwatch(...) object instead of the this.add.existing(new Stopwatch(...)) object in the scene’s update function.
Thanks again for your help, guys!

1 Like