Java 从游戏中移除子弹时的ConcurrentModificationException
我必须为我在大学的编程课程创建空间入侵者,这很好,但我在从游戏中移除子弹时遇到了问题 我把我所有的敌人和子弹都存储在不同的阵列列表中 这是我的主课Java 从游戏中移除子弹时的ConcurrentModificationException,java,arraylist,concurrentmodification,Java,Arraylist,Concurrentmodification,我必须为我在大学的编程课程创建空间入侵者,这很好,但我在从游戏中移除子弹时遇到了问题 我把我所有的敌人和子弹都存储在不同的阵列列表中 这是我的主课 package uk.ac.wnc.pot13000765.space_invaders; import java.util.ArrayList; import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMod
package uk.ac.wnc.pot13000765.space_invaders;
import java.util.ArrayList;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
public class SpaceInvaders {
private ArrayList<Enemy> enemies = new ArrayList<Enemy>();
private static ArrayList<Bullet> bullets = new ArrayList<Bullet>();
private Player player;
public SpaceInvaders() {
//Setup and create the OpenGL Context + Window
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("Unit 14 Space Invaders in Java by Liam Potter - POT13000765");
Display.create();
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glClearColor(0f, 0f, 0f, 1f);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
} catch(LWJGLException e) {
System.err.print(e);
System.exit(1);
}
Time.getDelta();
Time.setLastFps(Time.getTime());
//Setup
player = new Player(40, 40, 50, 50);
//Enemies
enemies.add(new Enemy(40, 540, 25, 25));
while(!Display.isCloseRequested()) {
gameLoop(Time.getDelta());
}
Display.destroy();
}
private void gameLoop(int delta) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
//Update
player.update(delta);
if(enemies.size() > 0) for(Enemy e: enemies) e.update(delta);
if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);
//Render
player.draw();
if(enemies.size() > 0) for(Enemy e: enemies) e.draw();
if(bullets.size() > 0) for(Bullet b: bullets) b.draw();
Display.sync(60);
Display.update();
Time.updateFps();
}
public int getWindowWidth() {
return Display.getWidth();
}
public int getWindowHeight() {
return Display.getHeight();
}
public static void spawnBullet(Bullet b) {
bullets.add(b);
}
public static void destroyBullet(Bullet b) {
bullets.remove(b);
}
public static void main(String[] args) {
new SpaceInvaders();
}
}
这正是我得到的错误:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.gameLoop(SpaceInvaders.java:62)
at uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.<init>(SpaceInvaders.java:50)
at uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.main(SpaceInvaders.java:91)
线程“main”java.util.ConcurrentModificationException中的异常
在java.util.ArrayList$Itr.checkForComodification处(未知源)
位于java.util.ArrayList$Itr.next(未知源)
在uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.gameLoop(SpaceInvaders.java:62)
在uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.(SpaceInvaders.java:50)
在uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.main(SpaceInvaders.java:91)
我知道我可以使用ListIterator来解决这个问题,但我不知道如何在我的主类中实现它们。这个循环:
package uk.ac.wnc.pot13000765.space_invaders;
import java.util.ArrayList;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
public class SpaceInvaders {
private ArrayList<Enemy> enemies = new ArrayList<Enemy>();
private static ArrayList<Bullet> bullets = new ArrayList<Bullet>();
private Player player;
public SpaceInvaders() {
//Setup and create the OpenGL Context + Window
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("Unit 14 Space Invaders in Java by Liam Potter - POT13000765");
Display.create();
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glClearColor(0f, 0f, 0f, 1f);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
} catch(LWJGLException e) {
System.err.print(e);
System.exit(1);
}
Time.getDelta();
Time.setLastFps(Time.getTime());
//Setup
player = new Player(40, 40, 50, 50);
//Enemies
enemies.add(new Enemy(40, 540, 25, 25));
while(!Display.isCloseRequested()) {
gameLoop(Time.getDelta());
}
Display.destroy();
}
private void gameLoop(int delta) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
//Update
player.update(delta);
if(enemies.size() > 0) for(Enemy e: enemies) e.update(delta);
if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);
//Render
player.draw();
if(enemies.size() > 0) for(Enemy e: enemies) e.draw();
if(bullets.size() > 0) for(Bullet b: bullets) b.draw();
Display.sync(60);
Display.update();
Time.updateFps();
}
public int getWindowWidth() {
return Display.getWidth();
}
public int getWindowHeight() {
return Display.getHeight();
}
public static void spawnBullet(Bullet b) {
bullets.add(b);
}
public static void destroyBullet(Bullet b) {
bullets.remove(b);
}
public static void main(String[] args) {
new SpaceInvaders();
}
}
if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);
调用Bullet.update,它可以调用您正在执行的dispose()
SpaceInvaders.destroyBullet(this);
它调用
bullets.remove(b);
所以本质上,存在这样一种情况,即在ArrayList上循环,并在循环时从中删除对象。这是不允许的。您可以改为使用CopyOnWriteArrayList,该操作是允许的。不过,这相当昂贵,因为它在进行修改时会复制整个阵列。另一种可能的解决方案是在dispose()中收集要删除的项目符号,并在更新循环后将其删除。发生这种情况的原因是您无法迭代ArrayList并同时修改元素。你能做的就是 (一)
Iteratorit=bullets.Iterator();
while(it.hasNext())
{
Bullet b=it.next();
项目符号。更新(b)
}
2) 此外(尽管我认为您应该做第一件事),您可以使用java.util.concurrent.CopyOnWriteArrayList,而不必更改代码。谢谢,我现在正在使用CopyOnWriteArrayList。目前,它的资源密集程度并不重要,因为我最多只能在两台机器上运行它。
Iterator< Bullet > it = bullets.iterator();
while (it.hasNext() )
{
Bullet b = it.next();
bullets.update(b)
}