我不知道我错过了什么......完整的代码非常大,所以我只是把这个部分放在这里抛出异常。
for (int i = 0; i < player.getBullets().size(); i++) { //for every player bullet
for (int j = 0; j < aliens.getAliens().size(); j++) { //for every player bullet every alien
player.getBullets().get(i);
aliens.getAliens().get(j);
if (player.getBullets().get(i).getBounds().intersects(aliens.getAliens().get(j).getBounds())){ //player bullet vs alien collison
if (aliens.getAliens().get(j).getType() == 1)
score += 2 + level;
else if(aliens.getAliens().get(j).getType() == 2)
score += 4 + level;
else
score += 8 + level*2;
aliens.getAliens().remove(j); // alien dies
player.getBullets().remove(i);
System.out.println("player bullet removed");
}
}
}
它在//玩家子弹与外星人碰撞线上引发了异常。
我添加了player.getBullets().get(i)
和getAliens()
来确定哪一个抛出了异常而且它是玩家一个。
错误似乎是随机的,但我相信当外星人侧身移动到子弹上时它会超出界限。如果子弹直接击中外星人,它可以正常工作。使用相交可能是错误吗?
顺便说一句,这是太空侵略者的模仿。任何帮助将不胜感激。
答案 0 :(得分:3)
在其集合中使用支持Iterator
操作的remove
。为了给你一个想法(删除OP中所有不相关的代码):
List<Bullet> bullets = new ArrayList<Bullet>();
List<Alien> aliens = new ArrayList<Alien>();
Iterator<Alien> alienIterator = aliens.iterator();
Iterator<Bullet> bulletIterator = bullets.iterator();
while (bulletIterator.hasNext()) { //for every player bullet
while (alienIterator.hasNext()) { //for every player bullet every alien
Bullet bullet = bulletIterator.next();
Alien alien = alienIterator.next();
if (bullet.getBounds().intersects(alien.getBounds())) { //player bullet vs alien collison
bulletIterator.remove();
alienIterator.remove();
System.out.println("player bullet removed");
}
}
}
请注意,如果您同时在其他地方修改外星人/子弹,它仍然容易受到IllegalStateException
的影响。
答案 1 :(得分:2)
您正在遍历它们时改变列表(通过在循环内调用.remove()
)。您正在检查与其发生碰撞的过程中删除子弹。
一种解决方案是为外星人/子弹/其他此类物品提供isDead
变量。然后,不要在循环内删除它们,而是等到循环之后,用isDead == true
删除所有人。
答案 2 :(得分:1)
问题是您要从正在遍历的阵列中删除项目。根据Javadoc:
int size()
Returns the number of elements in this collection.
这会产生一个数字,当你从集合中删除项目时,它会大于实际的集合大小,因此会导致超出界限。
您需要使用iterator遍历集合,然后在遍历集合时使用iterator.remove()从集合中删除项目。
答案 3 :(得分:1)
你应该创建迭代器来迭代玩家和外星人。然后,当应该删除一个迭代器而不是原始列表。这使循环工作。
正如@Toomai所建议的,不是删除,将它们标记为已死,可能会在以后删除它们,这也是一个不错的解决方案。
答案 4 :(得分:1)
让我们说玩家0被杀了。当你移除他的子弹时,所有其他子弹在索引中向下移动一个。因此,当索引增加到1时,您将查看最初的子弹2,而不是子弹1。
当按索引从List中删除时,总是以相反的顺序遍历循环,这样就不会影响仍然要查看的元素的顺序。
然而,如果最后一颗子弹杀死任何东西,你会看到(kapow)问题。当你仍然在for(j)循环中时,你删除了最后一颗子弹。对getBullet(i)的下一次调用将失败,因为不再有子弹i,现在只有i-1。当子弹杀死某些东西时,你应该突破内循环。 (假设子弹可以;一次杀死2个外星人)
那就是说,
你会得到更好的服务for (Bullet bullet : player.getBullets() {}
这将真正简化您的代码!!! 考虑不要动态删除。将要删除的所有内容收集到两个临时列表中,deadAliens和usedBullets。在循环调用结束时
aliens.getAliens()。removeAll(deadAliens); player.getBullets()的removeAll(deadBullets);
答案 5 :(得分:0)
在您的代码中,您要删除我认为是列表的项目
aliens.getAliens().remove(j); // alien dies
player.getBullets().remove(i)
当外循环的条件无效时,可能会发生在内循环中的循环。
答案 6 :(得分:0)
向我看看player.getBullets()。remove(i);删除一些东西,但你继续循环。你必须在System.out.println ...
之后突破内部for循环