轴对齐矩形碰撞检测 - Java
Axis Aligned Rectangle Collision Detection - Java
我在检查 2 个矩形是否与 4 点 碰撞时遇到一些问题,所以我有一个 rect1 和 p1(x,y)表示左下角,p2(x,y)表示右上角,同rect2.
这是我的图表插图:
到目前为止,这是我的示例代码:
int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};
if(rect1[1][0] >= rect2[0][0] && rect1[1][1] >= rect2[0][1] && rect1[0][0] <= rect2[1][0] && rect1[0][1] <= rect2[1][1])
{
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
我不太确定我用这段代码是否正确,任何人都可以给我一些想法吗? (我是初学者!)
简短回答:是
基本上你有四个条件你必须检查以确保你有碰撞矩形:
- 第一个矩形的右上角必须在第二个矩形左下角的右边
- 第一个矩形的右上角必须在第二个矩形的左下角上方
- 第一个矩形的左下角必须在第二个矩形右上角的左边
- 第一个矩形的左下角必须低于第二个矩形的右上角
像下面这样重构你的代码,上面四个条件是如何满足的会变得更清楚:
public class HelloWorld {
public static void main(String []args){
int[][] rect1 = {{1,5},{4,8}};
int[][] rect2 = {{4,1},{7,4}};
if( isRect1UpperRightCornerRightOfRect2BottomLeftCorner(rect1, rect2) &&
isRect1UpperRightCornerAboveRect2BottomLeftCorner(rect1, rect2) &&
isRect1BottomLeftCornerLeftOfRect2UpperRightCorner(rect1, rect2) &&
isRect1BottomLeftCornerBelowRect2UpperRightCorner(rect1, rect2) ) {
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
}
private static boolean isRect1UpperRightCornerRightOfRect2BottomLeftCorner(int[][] rect1, int[][] rect2) {
return rect1[1][0] >= rect2[0][0];
}
private static boolean isRect1UpperRightCornerAboveRect2BottomLeftCorner(int[][] rect1, int[][] rect2) {
return rect1[1][1] >= rect2[0][1];
}
private static boolean isRect1BottomLeftCornerLeftOfRect2UpperRightCorner(int[][] rect1, int[][] rect2) {
return rect1[0][0] <= rect2[1][0];
}
private static boolean isRect1BottomLeftCornerBelowRect2UpperRightCorner(int[][] rect1, int[][] rect2) {
return rect1[0][1] <= rect2[1][1];
}
}
同时 here is a good interactive website 直观地展示了上面的工作原理。注意角被翻转了。
首先,您的代码不会在 if
块中编译。有一个不匹配的左括号。我会删除它。
所以,让我们添加一些中间变量以更好地理解代码的含义:
int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};
int rect1X1 = rect1[0][0];
int rect1X2 = rect1[1][0];
int rect1Y1 = rect1[0][1];
int rect1Y2 = rect1[1][1];
int rect2X1 = rect2[0][0];
int rect2X2 = rect2[1][0];
int rect2Y1 = rect2[0][1];
int rect2Y2 = rect2[1][1];
if (rect1X2 >= rect2X1 && rect1Y2 >= rect2Y1 && rect1X1 <= rect2X2 && rect1Y1 <= rect2Y2)
{
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
现在,让我们分开每个轴的逻辑:
int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};
int rect1X1 = rect1[0][0];
int rect1X2 = rect1[1][0];
int rect1Y1 = rect1[0][1];
int rect1Y2 = rect1[1][1];
int rect2X1 = rect2[0][0];
int rect2X2 = rect2[1][0];
int rect2Y1 = rect2[0][1];
int rect2Y2 = rect2[1][1];
boolean xCollides = rect1X2 >= rect2X1 && rect1X1 <= rect2X2;
boolean yCollides = rect1Y2 >= rect2Y1 && rect1Y1 <= rect2Y2;
if (xCollides && yCollides)
{
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
我们怎样才能得到一个轴的碰撞?有 15 种形式的两个对象如何沿轴相对于彼此定位:
案例 1 - 完全重合碰撞:
X-----X
X-----X
案例 2、3、4、5、6 和 7 - 完全非重合碰撞:
X---X X---X X-----X
X-----X X-----X X---X
X-----X X-X X-----X
X-X X-----X X---X
情况 8 和 9 - 部分碰撞:
X---X X---X
X---X X---X
案例 10 和 11 - 勉强相撞:
X--X X--X
X--X X--X
案例 12 和 13 - 只是接触(不是碰撞):
X--X X-X
X-X X--X
情况 14 和 15 - 相距甚远(未碰撞):
X-X X-X
X-X X-X
您的代码应该在每个轴上将案例 1 到 11 与案例 12 到 15 分开。让我们看看它做了什么:
boolean xCollides = rect1X2 >= rect2X1 && rect1X1 <= rect2X2;
- 情况一:真与真->真
- 情况2:真与真->真
- 情况3:真与真->真
- 情况4:真与真->真
- 情况5:真与真->真
- 情况6:真与真->真
- 情况7:真与真->真
- 情况8:真与真->真
- 情况9:真与真->真
- 案例10:真与真->真
- 案例11:真与真->真
- 案例 12:假与真 -> 假
- 案例 13:真假 -> 假
- 案例 14:假与真 -> 假
- 案例 15:真假 -> 假
因此,您的代码能够将情况 1 到 11 与情况 12 到 15 分开,因此它对于 X 轴是正确的。Y 轴的代码等同于 X 轴的代码(在不同的轴),所以它也是正确的。 最后,我们得出结论,您的整个代码都是正确的。
我在检查 2 个矩形是否与 4 点 碰撞时遇到一些问题,所以我有一个 rect1 和 p1(x,y)表示左下角,p2(x,y)表示右上角,同rect2.
这是我的图表插图:
到目前为止,这是我的示例代码:
int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};
if(rect1[1][0] >= rect2[0][0] && rect1[1][1] >= rect2[0][1] && rect1[0][0] <= rect2[1][0] && rect1[0][1] <= rect2[1][1])
{
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
我不太确定我用这段代码是否正确,任何人都可以给我一些想法吗? (我是初学者!)
简短回答:是
基本上你有四个条件你必须检查以确保你有碰撞矩形:
- 第一个矩形的右上角必须在第二个矩形左下角的右边
- 第一个矩形的右上角必须在第二个矩形的左下角上方
- 第一个矩形的左下角必须在第二个矩形右上角的左边
- 第一个矩形的左下角必须低于第二个矩形的右上角
像下面这样重构你的代码,上面四个条件是如何满足的会变得更清楚:
public class HelloWorld {
public static void main(String []args){
int[][] rect1 = {{1,5},{4,8}};
int[][] rect2 = {{4,1},{7,4}};
if( isRect1UpperRightCornerRightOfRect2BottomLeftCorner(rect1, rect2) &&
isRect1UpperRightCornerAboveRect2BottomLeftCorner(rect1, rect2) &&
isRect1BottomLeftCornerLeftOfRect2UpperRightCorner(rect1, rect2) &&
isRect1BottomLeftCornerBelowRect2UpperRightCorner(rect1, rect2) ) {
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
}
private static boolean isRect1UpperRightCornerRightOfRect2BottomLeftCorner(int[][] rect1, int[][] rect2) {
return rect1[1][0] >= rect2[0][0];
}
private static boolean isRect1UpperRightCornerAboveRect2BottomLeftCorner(int[][] rect1, int[][] rect2) {
return rect1[1][1] >= rect2[0][1];
}
private static boolean isRect1BottomLeftCornerLeftOfRect2UpperRightCorner(int[][] rect1, int[][] rect2) {
return rect1[0][0] <= rect2[1][0];
}
private static boolean isRect1BottomLeftCornerBelowRect2UpperRightCorner(int[][] rect1, int[][] rect2) {
return rect1[0][1] <= rect2[1][1];
}
}
同时 here is a good interactive website 直观地展示了上面的工作原理。注意角被翻转了。
首先,您的代码不会在 if
块中编译。有一个不匹配的左括号。我会删除它。
所以,让我们添加一些中间变量以更好地理解代码的含义:
int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};
int rect1X1 = rect1[0][0];
int rect1X2 = rect1[1][0];
int rect1Y1 = rect1[0][1];
int rect1Y2 = rect1[1][1];
int rect2X1 = rect2[0][0];
int rect2X2 = rect2[1][0];
int rect2Y1 = rect2[0][1];
int rect2Y2 = rect2[1][1];
if (rect1X2 >= rect2X1 && rect1Y2 >= rect2Y1 && rect1X1 <= rect2X2 && rect1Y1 <= rect2Y2)
{
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
现在,让我们分开每个轴的逻辑:
int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};
int rect1X1 = rect1[0][0];
int rect1X2 = rect1[1][0];
int rect1Y1 = rect1[0][1];
int rect1Y2 = rect1[1][1];
int rect2X1 = rect2[0][0];
int rect2X2 = rect2[1][0];
int rect2Y1 = rect2[0][1];
int rect2Y2 = rect2[1][1];
boolean xCollides = rect1X2 >= rect2X1 && rect1X1 <= rect2X2;
boolean yCollides = rect1Y2 >= rect2Y1 && rect1Y1 <= rect2Y2;
if (xCollides && yCollides)
{
System.out.println("Collision");
} else {
System.out.println("No Collision");
}
我们怎样才能得到一个轴的碰撞?有 15 种形式的两个对象如何沿轴相对于彼此定位:
案例 1 - 完全重合碰撞:
X-----X
X-----X
案例 2、3、4、5、6 和 7 - 完全非重合碰撞:
X---X X---X X-----X
X-----X X-----X X---X
X-----X X-X X-----X
X-X X-----X X---X
情况 8 和 9 - 部分碰撞:
X---X X---X
X---X X---X
案例 10 和 11 - 勉强相撞:
X--X X--X
X--X X--X
案例 12 和 13 - 只是接触(不是碰撞):
X--X X-X
X-X X--X
情况 14 和 15 - 相距甚远(未碰撞):
X-X X-X
X-X X-X
您的代码应该在每个轴上将案例 1 到 11 与案例 12 到 15 分开。让我们看看它做了什么:
boolean xCollides = rect1X2 >= rect2X1 && rect1X1 <= rect2X2;
- 情况一:真与真->真
- 情况2:真与真->真
- 情况3:真与真->真
- 情况4:真与真->真
- 情况5:真与真->真
- 情况6:真与真->真
- 情况7:真与真->真
- 情况8:真与真->真
- 情况9:真与真->真
- 案例10:真与真->真
- 案例11:真与真->真
- 案例 12:假与真 -> 假
- 案例 13:真假 -> 假
- 案例 14:假与真 -> 假
- 案例 15:真假 -> 假
因此,您的代码能够将情况 1 到 11 与情况 12 到 15 分开,因此它对于 X 轴是正确的。Y 轴的代码等同于 X 轴的代码(在不同的轴),所以它也是正确的。 最后,我们得出结论,您的整个代码都是正确的。