Weastie
Weastie

Reputation: 157

Phaser.js delete object in group during forEach loop

I want to destroy an object after it passes a certain x value. The objects are part of a phaser group called balls. In my update loop, I have this line of code:

balls.forEach(updateBalls, null, true);

Here is the updateBalls function:

function updateBalls(ball) {
  if (ball.x > 800) {
    ball.destroy();
  }
}

The problem is that deleting the object during the loop messes up the loop, this is the error I get:

TypeError: this.children[i] is undefined

I tried to push each of the balls to an array and then destroying each ball like this.

function updateBalls(ball) {
  if (ball.x > 800) {
    ballsToDestroy.push(ball);
  }
}

Then in the update loop:

balls.forEach(updateBalls, null, true);
for (x = 0; x < ballsToDestroy.length; balls++) {
    ballsToDestroy[x].destroy();
}

This gave me some odd bugs though.
It works if I use ball.kill(), but that will eventually make the game lag because the balls aren't actually removed.

How can I get around this?

Upvotes: 4

Views: 1806

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074694

Sounds like a silly bug in Phaser, if Group#forEach fails when you call destroy on one of the objects in the group during the iteration.

According to the Phaser docs, a Group has a filter function returning an ArraySet. So you could get an ArraySet of balls to destroy:

var toDestroy = balls.filter(function(ball) { return ball.x <= 800; });

Then ArraySet says it has a handy callAll function that lets us call a function on all the entries. So we can destroy them using that:

toDestroy.callAll('destroy');

All in one:

balls.filter(function(ball) { return ball.x <= 800; }).callAll('destroy');

Or with ES2015+

balls.filter(ball => ball.x <= 800).callAll('destroy');

(The => and <= right near each other look funny there, but don't worry, the first one introduces an arrow function, the second is the less-than-or-equal operator.)

Upvotes: 5

Related Questions