简体   繁体   English

从游戏中删除子弹时出现ConcurrentModificationException

[英]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.

相关问题 从队列中添加/删除时获取 ConcurrentModificationException - Getting ConcurrentModificationException when adding/removing from queue 从列表中删除项目时出现 ConcurrentModificationException - ConcurrentModificationException when removing item from a list 从 ArrayLists 中删除对象时如何避免 concurrentModificationException” - how to avoid concurrentModificationException when removing an object from to ArrayLists" 从ArrayList中删除对象时如何避免ConcurrentModificationException - How to avoid a ConcurrentModificationException when removing objects from an ArrayList 从列表中添加子列表/从列表中删除子列表时出现java.util.ConcurrentModificationException - java.util.ConcurrentModificationException when adding/removing SubLists from/to lists 从父实体中删除时,Spring数据JPA @PreRemove ConcurrentModificationException - Spring data JPA @PreRemove ConcurrentModificationException when removing from parent enity 从HashMap中删除元素时发生异常java.util.ConcurrentModificationException - Exception when removing element from HashMap java.util.ConcurrentModificationException 从哈希图中删除元素时出现 java.util.ConcurrentModificationException - java.util.ConcurrentModificationException when removing elements from a hashmap ConcurrentModificationException从迭代器移除元素 - ConcurrentModificationException removing element from iterator ConcurrentModificationException,但不从ArrayList中删除任何内容 - ConcurrentModificationException but not removing anything from ArrayList
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM