Multiple object intersection and removal

Backwards loops are a great way to iterate & remove an array’s current item at the same time.

However you attempt to splice() the indices j & i from the same array at 1 swoop.

That makes all items inside that array to left-shift their indices 2 times while the outer loop is still dealing w/ its index i.

In short, we can’t use method splice() to delete more than 1 index from the same array on 1 single iteration.

As a workaround, rather than mutating the array inside that double loop, we merely collect on a separate array the indices marked to be removed later.

  • Let’s call that extra array toRemoveIndices[].
  • Before starting the double loop, we clear that array like this: toRemoveIndices.length = 0;
  • Now, inside the inner loop, we replace the splice() calling w/ toRemoveIndices.push(i, j);
  • Once the double loop is finished we can finally use splice() in order to delete each animat[]'s index matching the indices collected by toRemoveIndices[].
  • We can even create a function for that task. I’ve just named it as removeIndices().

The excerpt below are the changes I’ve made to your posted code:

const animats = [], toRemoveIndices = [];

function draw() {
  background(255, 100, 100);

  var j, i = animats.length;
  toRemoveIndices.length = 0;

  while (i--) {
    const a = animats[j = i];

    a.birth();
    a.grow();

    while (j--)  if (a.intersects(animats[j])) {
      toRemoveIndices.push(i, j);
      break;
    }
  }

  removeIndices(animats, toRemoveIndices);
}

function removeIndices(array, indices) {
  for (const index of indices)  array.splice(index, 1);
  return array;
}
2 Likes