Проблема с вашим кодом заключается в том, что вы меняете размер списка cb всякий раз, когда обнаруживаете пересечение, но затем продолжаете использовать тот же индекс. Например, если cb имеет 3 элемента, а b имеет 4, а третья (индекс = 2) компьютерная пуля пересекает первую пулю игрока, размер cb уменьшается до 2. Когда вы продолжаете проверять пулю второго игрока по третья компьютерная пуля, в cb осталось только два элемента, и игра вылетает.
Короче говоря, зацикливание списков и одновременное их изменение сложно.
Еще одна вещь, которую следует учитывать, это то, что если, например, компьютерная пуля пересекается с двумя пулями игрока, все три из них должны быть удалены. Но если пуля компьютера удаляется при обнаружении пули первого игрока, пуля второго игрока останется.
На самом деле могут быть цепочки пуль, соприкасающиеся друг с другом, поэтому удаление чего-либо из списка до того, как вы сделаете все пересечения, может привести к неверным результатам.
После веселого долгого времени, проведенного за размышлениями об этом, вот что я сделаю. Это гарантирует, что все, что нужно удалить, удаляется и не зависит от индексации.
ArrayList<Bullet> newB = new ArrayList<Bullet>(b);
ArrayList<Bullet> newCB = new ArrayList<Bullet>(cb);
for (Bullet pBullet : b) {
for (Bullet cBullet : cb) {
if (pBullet.rect.intersects(cBullet.rect)) {
newB.remove(pBullet);
newCB.remove(cBullet);
}
}
}
cb = newCB;
b = newB;