碰撞时从ArrayList中删除项目(Java)?

时间:2015-06-16 02:47:37

标签: java arraylist collision detection

作为序言,我搜索了论坛,但没有发现与我的具体情况有关。我刚刚开始学习Java一周前,这是我第一次涉足面向对象编程。

我正在构建一个基本游戏(在机制方面,有点像Space Invaders)。我有一个“Projectile”类,一个“FallingThings”类(它是我对掉落物体(Money,Friend,Enemy)的类的父类)。射击的每个射弹都存储在ArrayList中,就像Money,Friend和Enemy的每个实例一样(每个都在它们自己的ArrayList中)。

实现碰撞检测时会出现问题。首先,它需要多个子弹才能使碰撞机制起作用(我想我可能在这里搞砸了一些数字,但我不是100%肯定)。现在,有时在我发射多个子弹(并且它们已经很久)之后,检测到碰撞而没有我发射另一个子弹并且一个FallingThings对象从屏幕上消失。此外,在其他时候,多个对象一次消失。最奇怪的是,所有这些都是不一致的,并且不总是以相同的方式再现。但是,我与玩家角色的碰撞完美无缺。

任何人都有一些关于我如何解决这个问题的想法?我的代码如下:

“FallingThings”类中的方法(ArrayLists在StartingClass(主类)中定义)。

   public void checkBulletCollision(Rectangle rectangle) {

    for (int j = 0; j < Character.getProjectiles().size(); j++) {
        Projectile p = (Projectile) Character.getProjectiles().get(j);
        if (p.isVisible() == true) {

            for (int i = 0; i < StartingClass.getMoneys().size(); i++) {
                Money m = (Money) StartingClass.getMoneys().get(i);
                if (m.getR().intersects(rectangle)) {
                    m.remove(i);
                    System.out.println("bullet collision");
                }
            }
            for (int i = 0; i < StartingClass.getEnemies().size(); i++) {
                Enemy e = (Enemy) StartingClass.getEnemies().get(i);
                if (e.getR().intersects(rectangle)) {
                    e.remove(i);
                }
            }
            for (int i = 0; i < StartingClass.getFriends().size(); i++) {
                Friend f = (Friend) StartingClass.getFriends().get(i);
                if (f.getR().intersects(rectangle)) {
                    f.remove(i);
                }
            }
        }
    }
}   

我对弹丸的更新方法:

public void update() {
    y -= speedY;
    if (y < 0) {
        visible = false;
    }
    rectangle.setBounds(getRectangle());
}

我一直试图解决这个问题一整天,但仍然无法正确实施。我尝试过使用ListIterator,但这会导致程序冻结并抛出类型转换错误。

非常感谢你的帮助! =)

4 个答案:

答案 0 :(得分:1)

我怀疑您遇到了问题,因为您在循环显示该列表时通过索引从列表中删除项目。删除项目会导致索引计数器退出分配。尝试使用实际的Iterator。甚至无需考虑索引。 Iterator有针对这些情况的删除方法..

Iterator<Enemy> iterator = StartingClass.getEnemies().iterator();
while (iterator.hasNext()) {
    Enemy e = iterator.next();
    if (e.getR().intersects(rectangle)) {
        iterator.remove();
    }
}

答案 1 :(得分:0)

我不明白 m.remove 的作用,您从列表中获取该项目,然后在该项目上调用“删除”。你想从列表中删除它吗?

StartingClass.getMoneys().remove(i);

答案 2 :(得分:0)

看起来问题是您要让所有类型的循环运行。因此,即使在用你的射弹移除金钱之后,你也可以使用相同的射弹移除敌人和敌人 - 如果弹丸是从更大的东西或从.44马格南射出的话,这是可能的。 无论如何,对我来说,看起来你需要打破你的迭代一旦你用一个射弹移除一个项目..所以你的代码应该是(使用泛型和增强的循环):

foreachprojectile:
    for( Projectile projectile : Character.getProjectiles()){
        if (projectile.isVisible() == true) {

            Iterator<Money> iterator = StartingClass.getMoneys().iterator();
            while (iterator.hasNext()) {
                Money m = iterator.next();
                if (m.getR().intersects(rectangle)) {
                    iterator.remove();
                    projectile.setVisible(false); // or any other method that does similar
                    break foreachprojectile; //Found a hit, so do not 
                    //look for any more hits with current projectile
                }
            }
            //And so on..
        }
    }

以上代码可能会完成你想要的;但是这个逻辑可以更好地封装,以清楚地传达意图。

答案 3 :(得分:0)

我弄清楚出了什么问题并解决了问题。事实证明问题不在我的for循环实现中(尽管使用listIterator仍然更有效且更不容易出错,所以我仍然选择改变我的代码的那个方面),而是在实现中我的碰撞检测。我忘记了抛射物和矩形(用于射弹)是两个不同的物体,因此,矩形没有与抛射物一起移动,导致各种各样的问题。

我通过将矩形绘制到屏幕来确定问题来检查它的表现,当然,它只是停留在一个地方,而不是与射弹一起移动。我对射弹的update()方法进行了一些更改,以便在调用时,矩形随子弹移动。这导致了正确的碰撞检测和正常运行的程序!

非常感谢大家的帮助,我在这里学到了很多关于编写高效代码和调试技术的知识!对此,我真的非常感激! =)

相关问题