Bug Report: calling setScale on an object in an object pool causes the physics collider to be put in the incorrect position

I am currently using Phaser 0.18 and experiencing this issue. I am posting here because I am not certain this is a bug, but I’ll do my best to describe it.

I did see another issue in the forum here: [Phaser BUG?] Animation changing gameobject`s body position

while there are some similarities to my problem, it did not seem identical, so I am posting.

Here is the short version: when I am using Phaser.Arcade.Group with a pool of objects consisting of Phaser.Arcade.Sprite, I am experiencing an issue whereby the position of the body collider seems to be calculated correctly until I getFirstDead of the existing items. At this time, if (and only if) I have used setScale on the sprite, the calculation of the position of the collider is off.

This is tricky to explain, so I will use some images and gifs to illustrate what I am describing. Here is the setup code:

import Phaser from 'phaser';

import flaresJSON from '../../assets/particles/flares.json';
import flaresPNG from '../../assets/particles/flares.png';

class WonderBullet extends Phaser.Physics.Arcade.Sprite {
  constructor(scene, x, y) {
    super(scene, x, y, 'flares', 'red');
  }
  preload() {}

  fire(x, y) {
    //this.setScale(0.5);
    this.body.reset(x, y);
    this.setOrigin(0.5, 0.5);
    this.setSize(5, 5);
    this.setActive(true);
    this.setVisible(true);
    this.setVelocityX(300);
    this.lastX = this.x;
  }

  preUpdate(time, delta) {
    super.preUpdate(time, delta);

    if (this.x - this.lastX > 500) {
      this.setActive(false);
      this.setVisible(false);
    }
  }

  update() {
    
  }
}

export class WonderBullets extends Phaser.Physics.Arcade.Group {
  constructor(scene) {
    scene.load.atlas('flares', flaresPNG, flaresJSON);
    super(scene.physics.world, scene);

    this.createMultiple({
      frameQuantity: 2,
      key: 'wonder-bullet',
      active: false,
      visible: false,
      classType: WonderBullet
    });
  }

  rates = {
    bulletSpacing: 800,
    lastBullet: 0
  };

  fireBullet(x, y) {
    let bullet = this.getFirstDead(false);
    if (bullet && this.scene.time.now > this.rates.lastBullet) {
      bullet.fire(x, y);
      this.rates.lastBullet = this.scene.time.now + this.rates.bulletSpacing;
    }
  }
}

this code basically works. I am using the x,y coordinates to emit a bullet (which is one of the flares) in front of the player.


The bullet pool size is 2, and everything is working correctly. you can see that the ‘box’ in debug mode is in the center of the flare and that the velocity is being set, the size is set (otherwise it is very big).

Now watch when I uncomment the setSize, to reduce the size of the art for the bullet, (but not the collider).

import Phaser from 'phaser';

import flaresJSON from '../../assets/particles/flares.json';
import flaresPNG from '../../assets/particles/flares.png';

class WonderBullet extends Phaser.Physics.Arcade.Sprite {
  constructor(scene, x, y) {
    super(scene, x, y, 'flares', 'red');
  }
  preload() {}

  fire(x, y) {
   
    this.body.reset(x, y);
    this.setOrigin(0.5, 0.5);
    this.setSize(5, 5);
    this.setScale(0.2); ///<======THIS!
    this.setActive(true);
    this.setVisible(true);
    this.setVelocityX(300);
    this.lastX = this.x;
  }

  preUpdate(time, delta) {
    super.preUpdate(time, delta);

    if (this.x - this.lastX > 500) {
      this.setActive(false);
      this.setVisible(false);
    }
  }

  update() {
    
  }
}

export class WonderBullets extends Phaser.Physics.Arcade.Group {
  constructor(scene) {
    scene.load.atlas('flares', flaresPNG, flaresJSON);
    super(scene.physics.world, scene);

    this.createMultiple({
      frameQuantity: 2,
      key: 'wonder-bullet',
      active: false,
      visible: false,
      classType: WonderBullet
    });
  }

  rates = {
    bulletSpacing: 800,
    lastBullet: 0
  };

  fireBullet(x, y) {
    let bullet = this.getFirstDead(false);
    if (bullet && this.scene.time.now > this.rates.lastBullet) {
      bullet.fire(x, y);
      this.rates.lastBullet = this.scene.time.now + this.rates.bulletSpacing;
    }
  }
}


Notice the arcade collider ‘moves’ from the center to the top?

Here’s what I can see:

  1. First two bullets work great, but when I pull from the pool I get aberrant behavior when I scale.
  2. If I set the Scale before I call body.reset, then they never work, not even the first two.

There’s some sort of interplay between getting the dead items, scaling and resetting that is not producing the behavior I’d expect. There’s also a possibility I need to resequence things a certain way, but I’ve had no luck with getting the hitbox to be in the correct spot when the sprite is rescaled. I’ve tried many different orders.

Here is the corresponding github issue: https://github.com/photonstorm/phaser/issues/4709

It just occurred to me there is a 0.19 release that is very new, I’ll try to see if I can reproduce this problem in that release.

Just verified same behavior in 3.19