Java 使用 LinkedList 进行碰撞检测时游戏崩溃
Java game crash on collision detection with LinkedList
我正在制作一款基于 Space Invaders 的 2D java 游戏。在我的游戏 class 中,我有这 3 个字段:
//enemies left to kill
private LinkedList<Enemy> enemiesLeft = new LinkedList<Enemy>();
//enemies killed
private LinkedList<Enemy> enemiesKilled = new LinkedList<Enemy>();
//missiles that have been fired
private LinkedList<Missile> missiles = new LinkedList<Missile>();
在我的 checkCollision()
方法中,我 运行 通过 enemiesLeft
列表中的每个 Enemy
并检查与 [=18] 中每个 Missile
的冲突=] 列表,但它会抛出 ConcurrentModificationException
.
这里是 checkCollision()
方法:
private void checkCollisions(){
//make an iterator over enemies
ListIterator<Enemy> iterEnemies = enemiesLeft.listIterator();
//loop through enemies
while(iterEnemies.hasNext()){
//error is thrown at below line
Enemy e = iterEnemies.next(); //current Enemy
//go through each Missile
ListIterator<Missile> iterMissiles = missiles.listIterator();
while(iterMissiles.hasNext()){
Missile m = iterMissiles.next(); //current Missile
if(e.doesIntersect(m)){
//remove Enemy from enemiesLeft and add it to enemiesKilled list
enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
//remove Missile
missiles.remove(m);
}
}
}
updateScore();
}
这是我得到的错误:
java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at Game.checkCollisions(Game.java:168)
at Game.run(Game.java:197)
at Game.main(Game.java:279)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
在发生碰撞之前,游戏 运行 一直很流畅。
请帮助我!
问题出在迭代列表时修改了列表。如果要修改,则不允许在迭代时更改列表。
保存要删除的实例,然后在(伪代码)之后删除它们:
ArrayList<Item> ItemsToRemove = new ArrayList<Item>();
for(Item item : allItems){
if(shouldItemBeRemoved(item)){
ItemsToRemove.add(item)
}
}
//Remove the items for the allItems list
for(Item item : itemToRemove){
allItems.remove(item);
}
或使用迭代器删除项目:
iterMissiles.remove();
您可以使用 ListIterator 的 remove()
方法。
使用下面的代码代替 missiles.remove(m);
iterMissiles.remove();
从 enemiesLeft
中删除也是如此。
while(iterMissiles.hasNext()){
Missile m = iterMissiles.next(); //current Missile
if(e.doesIntersect(m)){
//remove Enemy from enemiesLeft and add it to enemiesKilled list
enemiesKilled.add(e);
iterEnemies.remove();
//remove Missile
iterMissiles.remove();
}
}
不能更改正在迭代的列表:
enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
应该是:
iterEnimies.remove();
enemiesKilled.add(e);
问题在这里:
while(iterMissiles.hasNext()){
Missile m = iterMissiles.next(); //current Missile
if(e.doesIntersect(m)){
//remove Enemy from enemiesLeft and add it to enemiesKilled list
enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
//remove Missile
missiles.remove(m);
}
您在遍历项目时尝试从 missiles
中删除项目。它抛出了 java.util.ConcurrentModificationException
在遍历 missiles
之前添加新列表:
LinkedList<Missile> missilesForRemove = new LinkedList<Missile>();
并添加到此列表 m
变量并在 while 循环后从原始 missiles
列表中删除此 missilesForRemove
:
missiles.removeAll(missilesForRemove);
我正在制作一款基于 Space Invaders 的 2D java 游戏。在我的游戏 class 中,我有这 3 个字段:
//enemies left to kill
private LinkedList<Enemy> enemiesLeft = new LinkedList<Enemy>();
//enemies killed
private LinkedList<Enemy> enemiesKilled = new LinkedList<Enemy>();
//missiles that have been fired
private LinkedList<Missile> missiles = new LinkedList<Missile>();
在我的 checkCollision()
方法中,我 运行 通过 enemiesLeft
列表中的每个 Enemy
并检查与 [=18] 中每个 Missile
的冲突=] 列表,但它会抛出 ConcurrentModificationException
.
这里是 checkCollision()
方法:
private void checkCollisions(){
//make an iterator over enemies
ListIterator<Enemy> iterEnemies = enemiesLeft.listIterator();
//loop through enemies
while(iterEnemies.hasNext()){
//error is thrown at below line
Enemy e = iterEnemies.next(); //current Enemy
//go through each Missile
ListIterator<Missile> iterMissiles = missiles.listIterator();
while(iterMissiles.hasNext()){
Missile m = iterMissiles.next(); //current Missile
if(e.doesIntersect(m)){
//remove Enemy from enemiesLeft and add it to enemiesKilled list
enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
//remove Missile
missiles.remove(m);
}
}
}
updateScore();
}
这是我得到的错误:
java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at Game.checkCollisions(Game.java:168)
at Game.run(Game.java:197)
at Game.main(Game.java:279)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
在发生碰撞之前,游戏 运行 一直很流畅。 请帮助我!
问题出在迭代列表时修改了列表。如果要修改,则不允许在迭代时更改列表。
保存要删除的实例,然后在(伪代码)之后删除它们:
ArrayList<Item> ItemsToRemove = new ArrayList<Item>();
for(Item item : allItems){
if(shouldItemBeRemoved(item)){
ItemsToRemove.add(item)
}
}
//Remove the items for the allItems list
for(Item item : itemToRemove){
allItems.remove(item);
}
或使用迭代器删除项目:
iterMissiles.remove();
您可以使用 ListIterator 的 remove()
方法。
使用下面的代码代替 missiles.remove(m);
iterMissiles.remove();
从 enemiesLeft
中删除也是如此。
while(iterMissiles.hasNext()){
Missile m = iterMissiles.next(); //current Missile
if(e.doesIntersect(m)){
//remove Enemy from enemiesLeft and add it to enemiesKilled list
enemiesKilled.add(e);
iterEnemies.remove();
//remove Missile
iterMissiles.remove();
}
}
不能更改正在迭代的列表:
enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
应该是:
iterEnimies.remove();
enemiesKilled.add(e);
问题在这里:
while(iterMissiles.hasNext()){
Missile m = iterMissiles.next(); //current Missile
if(e.doesIntersect(m)){
//remove Enemy from enemiesLeft and add it to enemiesKilled list
enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
//remove Missile
missiles.remove(m);
}
您在遍历项目时尝试从 missiles
中删除项目。它抛出了 java.util.ConcurrentModificationException
在遍历 missiles
之前添加新列表:
LinkedList<Missile> missilesForRemove = new LinkedList<Missile>();
并添加到此列表 m
变量并在 while 循环后从原始 missiles
列表中删除此 missilesForRemove
:
missiles.removeAll(missilesForRemove);