使用直线和矩形检查碰撞

时间:2014-12-13 00:55:09

标签: java collision-detection

是否可以使用Area对象检查与线的碰撞?

目前我正在这样做的方式不起作用:

运行时返回false。但线条非常清晰,触及矩形,实际上它完全在里面。

import java.awt.Rectangle;
import java.awt.geom.Area;
import java.awt.geom.Line2D;

public class collision {

public static void main(String[] args) {

    Area area1 = new Area(new Rectangle(0, 0, 100, 100));
    Area area2 = new Area(new Line2D.Double(0, 0, 100, 100));

    System.out.println(isColliding(area1, area2));
}

public static boolean isColliding(Area area1, Area area2) {
    if (area2 != null) {
        Area collide1 = new Area(area1);
        collide1.subtract(area2);
        if (!collide1.equals(area1)) {
            return true;
        }
    }

    return false;

}

}

2 个答案:

答案 0 :(得分:1)

我能够通过创建一个检查事物点的递归函数来解决这个问题。 设置深度越高,检查的准确度越高,但完成时间越长。我一直使用10作为我的深度(我认为沿着线检查2047点)并且我没有遇到任何性能损失。除非你的Area对象包含非常薄的部分,否则我认为你不需要更多。

如果您认为可以通过任何方式改进,我可以随意评论和修改我的方法:)

感谢ajb建议使用PathIterator,这让我有机会检查沿线的点。

public static boolean findPoints(Area area1, Line2D line1, int depth) {

    Point p1 = new Point((int) (line1.getX2() + line1.getX1()) / 2,
            (int) (line1.getY2() + line1.getY1()) / 2);

    if (depth == 0) {
        return false;
    }

    pointMiddle = new Point(p1);
    if (area1.contains(p1)) {
        return true;

    } else {
        return findPoints(area1, new Line2D.Double(p1, line1.getP2()),
                depth - 1)
                || findPoints(area1, new Line2D.Double(line1.getP1(), p1),
                        depth - 1);
    }

}

答案 1 :(得分:0)

如果正如您在评论中所说的那样,您知道始终会检查Line2DRectangle是否有冲突,那么您可以使用intersects Line2D方法(见javadoc):

public static void main(String[] args) {

    Rectangle rect1 = new Rectangle(0, 0, 100, 100);
    Line2D line2 = new Line2D.Double(0, 0, 100, 100);

    System.out.println(isColliding(rect1, line2));
}

public static boolean isColliding(Rectangle2D rect1, Line2D line2) {
    if (line2 != null) {
        return line2.intersects(rect1);
    }   
    return false;    
}

测试一条线是否与更一般的Area发生碰撞更加困难;我不认为图书馆里有这样的方法。如果Area由矩形构成,您可以尝试保存List个对象的数组(或Rectangle),并测试该线是否与其中任何一个相交。另一种方法:您可以尝试使用contains Area方法,该方法测试区域是否包含点。如果Line2D包含 <{1}}的端点,则该行与该区域发生冲突。如果两个端点都在区域之外,但该区域由直线(Area)组成,则可以从多边形中检索每个线段并测试该线是否与每个线段相交。您可以使用area.isPolygonal()执行此操作,然后在生成的路径迭代器上使用类似的内容:

area.getPathIterator(null)

double[] coords = new double[6]; double moveX, moveY, prevX, prevY, newX, newY; while (!pathIterator.isDone()) { switch (pathIterator.currentSegment(coords)) { case PathIterator.SEG_MOVETO: moveX = coords[0]; moveY = coords[1]; prevX = moveX; prevY = moveY; break; case PathIterator.SEG_LINETO: newX = coords[0]; newY = coords[1]; if ([line2 intersects the line from (prevX,prevY) to (newX,newY)]) { return true; } prevX = newX; prevY = newY; break; case PathIterator.SEG_QUADTO: case PathIterator.SEG_CUBICTO: throw new RuntimeException("What is a curve doing in my rectangle?"); case PathIterator.SEG_CLOSE: // go back to the last SEG_MOVETO point, usually the first point if ([line2 intersects the line from (prevX,prevY) to (moveX,moveY)]) { return true; } prevX = newX; prevY = newY; break; } } 中有一些方法可以测试一个线段是否与另一个线段相交。

注意:我根本没有测试过这个。我希望它有效。