与其他阵列列表中的对象进行碰撞检测,同时忽略其自身的对象

时间:2017-04-26 05:47:19

标签: java arraylist javafx collision-detection game-physics

我正在JavaFX中从零开始创建一个子弹般的地狱式太空射击游戏类型的游戏。 Raiden系列的一些东西。

关于我目前设置的一些背景知识:

我有三个数组列表。一个用于玩家角色,一个用于敌人角色,一个用于射弹。这些数组列表中的所有对象都来自名为“Entity”的父类的子类。也就是说,玩家角色,敌人角色和射弹类都是“实体”的孩子。

现在,每次游戏创建其中一个实体对象时,它都会被添加到各自的数组列表中。

示例:

//"playerEntities" is the array list
//"playerCharacter" is the object being added
private void addPlayerCharacter()
    {
        PlayerCharacter playerCharacter = new PlayerCharacter();

        playerEntities.add(playerCharacter);

        gameArea.getChildren().add(playerCharacter.getTempCharacter());
    }`
然后,我通过比较它们的边界和当前坐标来检查两个对象中任何一个之间的碰撞检测。如果对象相交,则会从各自的数组列表中删除它们。

示例:

@Override
public void checkCollision()
{
    if((!Game.playerEntities.isEmpty()) && (!Game.enemyEntities.isEmpty()))
    {
        for(int i = 0; i < Game.playerEntities.size(); i++)
        {
            for(int j = 0; j < Game.enemyEntities.size(); j++)
            {
                Entity firstEntity = Game.playerEntities.get(i);
                Entity secondEntity = Game.enemyEntities.get(j);

                if(firstEntity.location.x < secondEntity.location.x + (secondEntity.width) &&
                        firstEntity.location.x + (firstEntity.width) > secondEntity.location.x &&
                        firstEntity.location.y < secondEntity.location.y + (secondEntity.height) &&
                        firstEntity.location.y + (firstEntity.height) > secondEntity.location.y)
                {
                    Game.playerEntities.remove(firstEntity);
                    Game.enemyEntities.remove(secondEntity);
                }
            }
        }
    }   
}

即使我在检查数组列表中至少有一个元素才能进行比较之前,我仍然会遇到这些异常:

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
etc...

应该注意的是,一旦发生碰撞,屏幕上的物体就会消失。

我无法弄清楚如果数组列表在没有对象存在的情况下甚至无法调用以检查碰撞,或者如何在没有对象的情况下从屏幕上删除对象它们明显存在于数组列表中并且已经注册了碰撞。

我的主要目标是允许类似类型的实体不会相互冲突,同时在相反类型之间检测到冲突。也就是说,敌人将在不被删除的情况下相互穿过,但会与玩家角色和玩家角色的射弹相撞。有没有更简单的方法来实现这一点,或修复我目前的方法?我已经尝试了几个小时搞乱这个,我开始感到沮丧。

我错过了什么?

2 个答案:

答案 0 :(得分:0)

很简单......举个例子。

player.size == 3 enemy.size == 5

并且碰巧玩家nr 3与敌人nr 4相交。 然后你删除玩家2,现在player.size == 2,enemy.size == 4; 我== 3,j == 3。 这导致循环继续,试图将玩家(3)与敌人(3)进行比较。播放器3不存在,会导致数组超出范围。

for(int i = 0; i < Game.playerEntities.size(); i++)
    {
        for(int j = 0; j < Game.enemyEntities.size() && i < Game.playerEntities.size(); j++)
        {
            Entity firstEntity = Game.playerEntities.get(i);
            Entity secondEntity = Game.enemyEntities.get(j);

            if(firstEntity.location.x < secondEntity.location.x + (secondEntity.width) &&
                    firstEntity.location.x + (firstEntity.width) > secondEntity.location.x &&
                    firstEntity.location.y < secondEntity.location.y + (secondEntity.height) &&
                    firstEntity.location.y + (firstEntity.height) > secondEntity.location.y)
            {
                Game.playerEntities.remove(firstEntity);
                Game.enemyEntities.remove(secondEntity);
            }
        }
    }

内环状况的改变应该可以解决您的问题。你也可以介绍一下&#34;继续&#34;:

for(int i = 0; i < Game.playerEntities.size(); i++)
    {
        for(int j = 0; j < Game.enemyEntities.size(); j++)
        {
            Entity firstEntity = Game.playerEntities.get(i);
            Entity secondEntity = Game.enemyEntities.get(j);

            if(firstEntity.location.x < secondEntity.location.x + (secondEntity.width) &&
                    firstEntity.location.x + (firstEntity.width) > secondEntity.location.x &&
                    firstEntity.location.y < secondEntity.location.y + (secondEntity.height) &&
                    firstEntity.location.y + (firstEntity.height) > secondEntity.location.y)
            {
                Game.playerEntities.remove(firstEntity);
                Game.enemyEntities.remove(secondEntity);
                continue;
                }
            }
        }

答案 1 :(得分:0)

我认为这不会起作用,因为你要删除一些对象:

TCommunicationClient

所以我会做以下事情:

  • 删除基于索引的
  • 始终向后删除
  • 检查碰撞后
  • 删除:

    Game.playerEntities.remove(firstEntity);
    Game.enemyEntities.remove(secondEntity);
    

    然后,碰撞检查中的代码必须是:

    List<Integer> indices_to_remove_player=new ArrayList<Integer>();
    List<Integer> indices_to_remove_enemies=new ArrayList<Integer>();
    
    在for循环之后

    indices_to_remove_player.add(i);
    indices_to_remove_enemies.add(j);
    

逻辑上,这是唯一的方法:想象一下,有三艘船崩溃:

  • 敌人1 敌人2的玩家
    • v以这种方式进入杰克的解决方案
    • v ^ enemy1与玩家 - 如果倒退则不会被删除
    • v ^ enemy2与玩家 - 当你跟随杰克的时候不会被删除 溶液
    • ^这样你去反转for-loops

现在,您正在检测玩家和敌人1之间的碰撞。两者都被删除。现在敌人2没有被移除,只是因为它在列表的后面位置,因此玩家不再存在,即使两艘船同时与玩家一起崩溃。 注意:如果您反转&#39;你的循环:

for (int r=indices_to_remove_player.size()-1; r >= 0; r++) {
     Game.playerEntities.remove(indices_to_remove_player[r]);
}
for (int e=indices_to_remove_enemies.size()-1; e >= 0; e++) {
     Game.enemyEntities.remove(indices_to_remove_enemies[r]);
}

但是之后你会遇到我之前提到的问题,只是现在第一个对象来到最后,所以敌人2和玩家将被移除,但不会被敌人1。 如果您对此有任何疑问,请随时发表评论。 希望这会有所帮助。