检查两个对象之间交集的算法

时间:2017-05-13 22:47:08

标签: java algorithm geometry collision-detection intersection

我正在编写一个小游戏,我在交叉路口遇到了一些问题。我需要一个有效的算法来检查两个对象(有x和y坐标,还有宽度和高度)是否相交。

我尝试了以下内容,但它并不总是有效,有时它不会识别交叉点。

    public boolean contains(int x, int y) {
    if ((x < this.x + this.width) && (x >= this.x) && (y < this.y + this.height) && (y >= this.y))
        return true;
    else
        return false;
}

我有一个包含对象的ArrayList,我执行以下操作:

    private boolean checkIntersection(String pDirection) {

    for (int i = 0; i < walls.size(); i++) {
        if (pDirection.equalsIgnoreCase("right") && car.contains(walls.get(i).getX() - 1, walls.get(i).getY()))
            return true;
        if (pDirection.equalsIgnoreCase("left") && car.contains(walls.get(i).getX() + 30, walls.get(i).getY()))
            return true;
        if (pDirection.equalsIgnoreCase("top") && car.contains(walls.get(i).getX(), walls.get(i).getY() + 30))
            return true;
        if (pDirection.equalsIgnoreCase("down") && car.contains(walls.get(i).getX(), walls.get(i).getY() - 1))
            return true;
    }
    return false;
}

注意“-1”和“+30”是为了避免汽车进入“墙壁”,那里的墙壁宽度为30,高度为30.汽车也有相同的尺寸。

另请注意,x和y是矩形的左上角。汽车和墙壁是矩形。

我很感谢你的帮助。

信息:如果我在墙上方并且我将方向改为“向下”或反之,则它不会在一排墙的开始处重新识别交叉点。 See picture

编辑1(我尝试反转对象,但它也不总是有效):

private boolean checkIntersection(String pDirection) {

    for (int i = 0; i < walls.size(); i++) {
        if (pDirection.equals("right") && walls.get(i).contains(car.getX() + 30, car.getY()))
            return false;
        if (pDirection.equals("left") && walls.get(i).contains(car.getX() - 1, car.getY()))
            return false;
        if (pDirection.equals("top") && walls.get(i).contains(car.getX(), car.getY() - 1))
            return false;
        if (pDirection.equals("down") && walls.get(i).contains(car.getX(), car.getY() + 30))
            return false;
    }
    return true;
}

2 个答案:

答案 0 :(得分:0)

算法中的缺陷是,你总是检查墙的左上角是否汽车中。但是,这并不等同于交叉。

相反,您应检查其中任何一个对象是否包含(至少)另一个对象的一个​​角(不一定是左上角)。

请注意,您应对两侧执行此检查,即车辆包含墙壁的任何角落或墙壁包含汽车的任何角落。

答案 1 :(得分:0)

我解决了以下面的方式修改contains方法,它现在完美无缺:

public boolean contains(int x, int y) {
        if ((x < this.x + this.width) && (x > this.x-this.width) && (y < this.y + this.height) && (y > this.y-this.height))
            return true;
        else
            return false;
    }

我认为我不由自主地做了(检查非交叉而不是交叉),但我可以使用@samgak和@Gene的答案/建议来优化它。谢谢,问题解决了。