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