我必须为我在大学的编程课程创建太空入侵者,这很好,但我在游戏中移除子弹时遇到了问题。
我将所有敌人和子弹存储在单独的ArrayLists中。
这是我的主要课程。
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();
}
}
这是我的子弹课程:
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);
}
}
这是我得到的确切错误:
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)
我知道我可以使用ListIterators来解决这个问题,但我无法弄清楚如何在我的主类中实现它们。
答案 0 :(得分:3)
这个循环:
if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);
调用Bullet.update,它可以调用你正在做的dispose()
SpaceInvaders.destroyBullet(this);
调用
bullets.remove(b);
基本上,有一种情况是你循环遍历ArrayList并在循环时从中删除对象。这是不允许的。您可以使用CopyOnWriteArrayList,在那里允许操作。然而,这是相当昂贵的,因为它在进行修改时复制整个阵列。另一种可能的解决方案是收集要在dispose()中删除的项目符号,并在更新循环后删除它们。
答案 1 :(得分:0)
这是因为您无法迭代ArrayList并同时修改元素。你能做的是
1)
Iterator< Bullet > it = bullets.iterator();
while (it.hasNext() )
{
Bullet b = it.next();
bullets.update(b)
}
2)另外(虽然我相信你应该做第一件事)你可以使用java.util.concurrent.CopyOnWriteArrayList而不是改变你的代码。