两个Shape对象之间的Java碰撞检测?

时间:2013-03-28 19:48:50

标签: java 2d collision shape intersection

我想知道判断Shape对象是否与另一个形状相交的最佳方法。 目前我在我的游戏中进行了碰撞检测,只要它涉及一个与矩形相交的形状,反之亦然。我遇到的问题是Shape类中的intersects()方法只能将Rectangle或Point作为参数,而不是另一个Shape。有没有一种有效的方法来测试两个Shape对象是否以任何方式重叠? 我试过的一种方法是使用for循环来生成一个点区域来测试它们是否在形状中,然后构建一个Point对象数组以发送到另一个形状进行测试,但这显着降低了我的帧率因为所有不必要的比较。

我在这里寻找并寻找类似的东西,但没有找到任何真正的东西。如果这是重复,请提前抱歉。

4 个答案:

答案 0 :(得分:17)

未经测试,但为何不测试:

import java.awt.geom.Area;

...

public static boolean testIntersection(Shape shapeA, Shape shapeB) {
   Area areaA = new Area(shapeA);
   areaA.intersect(new Area(shapeB));
   return !areaA.isEmpty();
}

Area实现Shape,但添加了一些可能有用的方法

答案 1 :(得分:5)

您还可以使用形状本身的边界,然后比较边界:

public boolean collidesWith(Shape other) {
    return shape.getBounds2D().intersects(other.getBounds2D());
}

这对眼睛来说有点好看。

答案 2 :(得分:1)

尽管user2221343已经回答了Monkeybro10的问题,但我认为在某些情况下知道如果你使用他描述的技术,形状轮廓可能会起作用可能会有所帮助:

例如,如果绘制两个多边形,如果它只出现在多边形的精确轮廓上,则不会检测到它们的碰撞。只有当多边形内包含的区域时才会出现。轮廓将重叠,检测到碰撞。 如果填充两个多边形但不绘制它们,即使在可见区域的轮廓上也会检测到碰撞。

我写了一个小例子来说明我的意思。取消注释绘制或填充命令,并通过取消注释给定的行,将第二个多边形垂直上升一个像素。运行代码并在JFrame中查看结果。如果第二个多边形上升,并且两个多边形只能通过"填充"命令,它们与轮廓相交并检测到碰撞。如果第二个多边形没有上升,则两个多边形都可以通过" draw"命令,它们与轮廓相交但未检测到碰撞:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.geom.Area;

import javax.swing.JFrame;

public class Test {

    private JFrame frame;
    private Polygon polygon1;
    private Polygon polygon2;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Test window = new Test();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Test() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame(){
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g){

                super.paint(g);

                doDrawing(g);

            }
        };
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        int nShape1 = 4;
        int xPoly1[] = {30,50,50,30};
        int yPoly1[] = {30,30,50,50};
        polygon1 = new Polygon(xPoly1,yPoly1,nShape1);

        int nShape2 = 4;
        int xPoly2[] = {35,55,55,35};
        int yPoly2[] = {50,50,70,70};

        // uncomment next line to rise second polygon vertically by one pixel
        //yPoly2[] = {49,49,69,69};

        polygon2 = new Polygon(xPoly2,yPoly2,nShape2);
    }
    public synchronized void doDrawing(Graphics g){
        g.setColor(new Color(255,0,0));

        // if you draw the polygon, collision on the exact outline won't be detected.
        // uncomment draw or fill command to see what I mean.
        g.drawPolygon(polygon1);
        g.fillPolygon(polygon1);

        g.setColor(new Color(0,0,255));

        // if you draw the polygon, collision on the exact outline won't be detected.
        // uncomment draw or fill command to see what I mean.
        g.drawPolygon(polygon2);
        g.fillPolygon(polygon2);

        Area area = new Area(polygon1);
        area.intersect(new Area(polygon2));
        if(!area.isEmpty()){
            System.out.println("intersects: yes");
        }
        else{
            System.out.println("intersects: no");
        }
    }

}

答案 3 :(得分:0)

如果您认为该区域相交太贵,您可以先进行边界检查:      shapeA.getBounds()。相交(shapeB.getBounds())

如果通过,则区域相交检查。

if( myShape.getBounds().intersects(otherShape.getBounds()) ){
    Area a = new Area(myShape);
    a.intersect(new Area(otherShape));
    if(!a.isEmpty()){
        // do something
    }
}