New Container don't update childs

Hi there,

I’m trying to use a class extending Container properties in order to move a character (who has a lifebar, a weapon, etc).
However, if using this.scene.add.container(0,0, [this.sprite]) is fine, a Container instanciation refuse to work:

 export default class Character extends Phaser.GameObjects.Container {

  /**
   * Character group with different sprite parts
   */
  constructor(scene, x, y, frame, name) {
    super(scene);

    this.x = x;
    this.y = y;

    this.sprite = this.scene.add.sprite(
      x,
      y,
      'unitsSpriteSheet',
      this.frame)
      .setOrigin(0, 0.3);
    this.sprite.name = 'bodyPart';

    this.add(this.sprite);
    this.scene.add.existing(this);
  }

In scene, I can move the container (console show his x/y updating), but the sprite doesn’t move. However, I can update sprite.x/y directly.

  update() {
    Game.gameMap.player.x += 1; //move containers coordinates, not sprite ones
    Game.gameMap.player.sprite.x += 1; //moving sprite directly is fine
  }

I noticed a similar topic here : https://phaser.discourse.group/t/container-doesnt-render-children-when-declared-by-new-keyword/5383
If it resolved displaying issue, it seems it doesn’t work for moving.

Am I missing something with Container instanciation ?
I know I can basically use this.scene.add.container, but why using this step when my class could implement Container’s properties ?

Thank you for your insights :slight_smile:

Remove

this.x = x; // 0 → undefined
this.y = y; // 0 → undefined

I’m surprised, why ?
Is it not the point to use the container position instead of sprite position, in order to move all children ?

Thanks for your quick response!

How are you instantiating Character?

This works fine:

class Character extends Phaser.GameObjects.Container {
    constructor(scene, x, y, frame, name) {
        super(scene, x, y);

        this.sprite = this.scene.add.sprite(0, 0, 'lemming', frame).setOrigin(0, 0.3);
        this.sprite.name = name;
        this.add(this.sprite);

        this.scene.add.existing(this);
    }
}

// …

function create() {
    var container = this.add.existing(new Character(this, 100, 50));
}

I don’t think you want to use the same coordinates (x, y) for both the container and sprite, that usually doesn’t make sense.

2 Likes

Thank you, it indeed works fine.

I omit that super would use container x and y, so this.x and this.y are irrelevant.

I saw that you can embed containers in containers ; what about containers and other objects ?

export default class Panel extends Phaser.GameObjects.Container {

/**
 * Panel manager
 */
constructor(scene, x, y, action) {
    super(scene, x, y);
    this.scene = scene;
    this.width = 100;
    this.height = 50;
    this.depth = 6;

    this.scene.add.existing(this);
    //this.add(action);   //Doesn't work, blendMode error
    this.add(action.rect); //works
    this.add(action.text);
}

I was wondering, if I have an “action” gameObject, containing graphics (such as a rectangle, a text…). Do I have to use an intermediate container ?
I tried to only add the gameObject, but Phaser is crashing. It seems that sub objects, are not understood if put in that way:

export default class ActionButton extends Phaser.GameObjects.GameObject {

/**
 * Panel action button
 */
constructor(scene) {
    super(scene);
    this.scene = scene;
    this.x = 0;
    this.y = 0;
    this.width = 100;
    this.height = 50;
    this.rect = new Phaser.GameObjects.Rectangle(scene, this.x, this.y, 120, 30, 0x303030).setOrigin(0,0);
    this.text = new Phaser.GameObjects.Text(scene, this.x+5, this.y+10, 'Fin de tour');
    this.rect.depth = 6;
    this.text.depth = 6;
    this.text.setText('Test');
    this.alpha = 1;
    this.rect.setInteractive();

    this.scene.add.existing(this);
    this.scene.add.existing(this.rect);
    this.scene.add.existing(this.text);
}

Do we have a simpler way to add these sub-childs to the container instead of registering each one ?
The doc is still a bit elusive about that