[英]ConcurrentModificationException when removing bullet from game
I have to create Space Invaders for my programming course in college which would be fine but I have a problem with removing a bullet from the game. 我必须为我在大学的编程课程创建太空入侵者,这很好,但我在游戏中删除子弹时遇到了问题。
I'm storing all my enemies and bullets in separate ArrayLists. 我将所有敌人和子弹存储在单独的ArrayLists中。
This is my main class. 这是我的主要课程。
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();
}
}
And this is my Bullet class: 这是我的Bullet类:
package uk.ac.wnc.pot13000765.space_invaders;
import org.lwjgl.opengl.GL11;
public class Bullet extends Entity {
public Bullet(int x, int y, int width, int height) {
super(x, y, width, height);
}
@Override
public void update(int delta) {
if(!(getY() > 600)) setY(getY() + 1);
else dispose();
System.out.println(getY());
}
@Override
public void draw() {
GL11.glColor3f(1.0f, 0.5f, 0.5f);
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2i(getX(), getY());
GL11.glVertex2i(getX() + getWidth(), getY());
GL11.glVertex2i(getX() + getWidth(), getY() + getHeight());
GL11.glVertex2i(getX(), getY() + getHeight());
GL11.glEnd();
}
@Override
public void dispose() {
SpaceInvaders.destroyBullet(this);
}
}
This is the exact error I am getting: 这是我得到的确切错误:
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)
I understand that I can use ListIterators to fix this but I can't figure out how to implement them in my main class. 我知道我可以使用ListIterators来解决这个问题,但我无法弄清楚如何在我的主类中实现它们。
This loop: 这个循环:
if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);
calls Bullet.update which can call dispose() in which you're doing 调用Bullet.update,它可以调用你正在做的dispose()
SpaceInvaders.destroyBullet(this);
which invokes 调用
bullets.remove(b);
So essentially, there is a situation in which you're looping over an ArrayList and remove objects from it while looping. 从本质上讲,有一种情况是你循环遍历ArrayList并在循环时从中删除对象。 That is not allowed.
这是不允许的。 You could use a CopyOnWriteArrayList instead, the operation is allowed there.
您可以使用CopyOnWriteArrayList,在那里允许操作。 This is rather expensive, though, as it copies the whole array when doing a modification.
然而,这是相当昂贵的,因为它在进行修改时复制整个阵列。 Another possible solution would be collecting the Bullets to be removed in dispose() and removing them after the update loop.
另一种可能的解决方案是收集要在dispose()中删除的项目符号,并在更新循环后删除它们。
This happens because you cannot iterate through the ArrayList and modify the elements in the same time. 发生这种情况是因为您无法迭代ArrayList并同时修改元素。 What you can do is
你能做的是
1) 1)
Iterator< Bullet > it = bullets.iterator();
while (it.hasNext() )
{
Bullet b = it.next();
bullets.update(b)
}
2) Also (though I believe you should do the first thing) you can use a java.util.concurrent.CopyOnWriteArrayList and not change your code. 2)另外(虽然我相信你应该做第一件事)你可以使用java.util.concurrent.CopyOnWriteArrayList而不是改变你的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.