Java项目未从LinkedList中删除

时间:2015-06-29 00:43:06

标签: java linked-list

我正在制作一个简单的视频游戏,我很快就遇到了一个问题,我无法修复......我的游戏中有很多敌人,所以当然它们都是从一个类{{{ 1}}。但是当玩家和敌人发生碰撞时,敌人不会被移除......这是我的EnemyEntityBlueEnemyController的代码。我假设我的Enemy课程没问题,因为我的播放器在碰撞时会消失。

Entity.java

Player

BlueEnemy.java

package com.darksunproductions.ld47.Entities;

import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

import com.darksunproductions.ld47.Game.Game;

public class Entity {

    private int x;
    private int y;
    private Point pos;
    private double velX;
    private double velY;
    private BufferedImage icon;
    private boolean dead = false;
    private int updatesSinceDeath = -1;

    protected Game game;

    protected Entity(int x, int y, double velX, double velY, Game game, BufferedImage icon){
        this.x = x;
        this.y = y;
        this.velX = velX;
        this.velY = velY;
        this.game = game;
        this.icon = icon;
    }

    public void setUpdatesSinceDeath(int i){
        updatesSinceDeath = i;
    }
    public int getUpdatesSinceDeath(){
        return updatesSinceDeath;
    }
    public boolean isDead(){
        return dead;
    }
    public void kill(){
        dead = true;
        updatesSinceDeath = 0;
        try{
            icon = ImageIO.read(new File("Explosion.png"));
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public Point topLeft(){
        return new Point(x, y);
    }
    public Point topRight(){
        return new Point(x+icon.getWidth(), y);
    }
    public Point bottomLeft(){
        return new Point(x, y+icon.getHeight());
    }
    public Point bottomRight(){
        return new Point(x+icon.getWidth(), y+icon.getHeight());
    }
    public void setX(int x){
        this.x = x;
    }
    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y){
        this.y = y;
    }
    public double getVelX() {
        return velX;
    }
    public void setVelX(double velX) {
        this.velX = velX;
    }
    public double getVelY() {
        return velY;
    }
    public void setVelY(double velY) {
        this.velY = velY;
    }
    public BufferedImage getIcon() {
        return icon;
    }
    public void setIcon(BufferedImage icon) {
        this.icon = icon;
    }
}

Controller.java

package com.darksunproductions.ld47.Entities;

import java.io.File;

import javax.imageio.ImageIO;

import com.darksunproductions.ld47.Game.Drawable;
import com.darksunproductions.ld47.Game.Game;

public class BlueEnemy extends Enemy implements Drawable{

    public BlueEnemy(int x, int y, double velX, double velY, Game game){
        super(x, y, velX, velY, game, null, Type.BLUE);

        try{
            setIcon(ImageIO.read(new File("Blue_Enemy.png")));
        }catch(Exception e){
            setIcon(null);
        }
    }

}

Enemy.java

package com.darksunproductions.ld47.Game;

import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;

import com.darksunproductions.ld47.Entities.Enemy;
import com.darksunproductions.ld47.Entities.Entity;
import com.darksunproductions.ld47.Entities.Player;

public class Controller {

    LinkedList<Drawable> entities = new LinkedList<Drawable>();
    Game game;

    public Controller(Game g){
        game = g;
    }

    public void testCollision(int startID){
        if(entities.size() > 0){
            Entity e1 = (Entity) entities.get(startID);
            Point corner[] = new Point[4];
            corner[0] = e1.topLeft();
            corner[1] = e1.topRight();
            corner[2] = e1.bottomLeft();
            corner[3] = e1.bottomRight();
            for (int e = startID + 1; e < entities.size(); e++) {
                Entity e2 = (Entity) entities.get(e);
                for (int c = 0; c < 4; c++) {
                    if (corner[c].x > e2.topLeft().x && corner[c].x < e2.topRight().x) {
                        if (corner[c].y > e2.topLeft().y && corner[c].y < e2.bottomLeft().y) {
                            collide(e1, e2);
                        }
                    }
                }
            }
        }
    }

    public void collide(Entity e1, Entity e2){
        if(e1 instanceof Player && !e1.isDead()){
            if(e2 instanceof Enemy && !e2.isDead()){
                e1.kill();
                e2.kill();
            }
        }
    }

    public void update(){
        if(entities.size() > 0){
            for(Drawable d : entities)
                d.update();
        }
    }

    public void render(Graphics g){
        if(entities.size() > 0){
            for(Drawable d : entities)
                d.render(g);
        }
    }

    public void add(Drawable d){
        entities.add(d);
    }

    public void remove(Drawable d){
        entities.remove(d);
    }

    public void remove(int i){
        entities.remove(i);
    }

    public int size(){
        return entities.size();
    }
    public int getIdOf(Entity e){
        for(int i = 0; i < entities.size(); i++){
            if(e == (Entity)entities.get(i))
                return i;
        }
        return -1;
    }
    public int getIdOf(Drawable d){
        Entity e = (Entity)d;
        for(int i = 0; i < entities.size(); i++){
            if(e == (Entity)entities.get(i))
                return i;
        }
        return -1;
    }

}

以下是碰撞时遇到的问题:

package com.darksunproductions.ld47.Entities;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import com.darksunproductions.ld47.Game.Drawable;
import com.darksunproductions.ld47.Game.Game;

public class Enemy extends Entity implements Drawable{

    public enum Type{
        BLUE
    }

    private Type type;

    public Enemy(int x, int y, double velX, double velY, Game game, BufferedImage icon, Type type){
        super(x, y, velX, velY, game, icon);
        this.type = type;
    }

    public void render(Graphics g){
        if(getIcon() != null)
            g.drawImage(getIcon(), getX(), getY(), null);
    }

    public void update(){
        if(getUpdatesSinceDeath() < 0){

            setY(getY() + (int)getVelY());

            if(getY() > 550){
                setY(-50);
                setX((int)(Math.random()*468));
            }

        }else if(getUpdatesSinceDeath() >= 0){
            setUpdatesSinceDeath(getUpdatesSinceDeath() + 1);
            if(getUpdatesSinceDeath() > 60){
                game.c.remove(this);
            }
        }
    }

}

除了一个小问题......当我点击Exception in thread "Thread-1" java.util.ConcurrentModificationException at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:778) at java.util.LinkedList$ListItr.next(LinkedList.java:713) at com.darksunproductions.ld47.Game.Controller.update(Controller.java:52) at com.darksunproductions.ld47.Game.Game.update(Game.java:58) at com.darksunproductions.ld47.Game.Game.run(Game.java:78) at java.lang.Thread.run(Thread.java:701) 时,Eclipse表示LinkedList没有第778行......

提前感谢您提供任何帮助......

2 个答案:

答案 0 :(得分:3)

game.c.remove(this);是糟糕设计的一个很好的指标,实体不负责决定何时删除它,只是向Controller提供可以使用的信息

主要问题是增强循环涉及List&#39; Iterator,这会阻止在迭代它时修改基础List。< / p>

相反,请自行使用List s Iterator,当Controller确定某个实体已失效(死亡或曾经)时,请使用Iterator&# 39; s remove方法删除它,例如

public void update(){
    if(entities.size() > 0){
        LinkedList<Drawable> entities = new LinkedList<>();
        while (it.hasNext()) {
            Drawable d = it.next();
            d.update();
            // Or what ever flag you want to use
            if (d.isRemovable()) {
                it.remove(d);
            }
        }
    }
}

答案 1 :(得分:1)

我认为game.c是BlueEnemy类中的控制器,在这种情况下,您在控制器中循环可能会删除的列表。这就是并发修改异常的原因。你可以循环遍历列表的副本,这将是一种解决方法。