本文主要是介绍圆与旋转矩形的碰撞检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
圆与旋转矩形的碰撞检测
本文我将解释如何实现圆和旋转矩形的碰撞检测。碰撞检测用于确定对象A是否碰撞了对象B。圆包含圆心位置x,y和一个半径。矩形包含左上角的x,y位置、宽度、长度和一个可以旋转的角度。我们假设矩形沿着它的中心点旋转。
我将使用一个小程序、图片和代码来展示这一点。为了更好地理解圆和不旋转矩形之间的碰撞检测,可以阅读这篇文章
程序示例
这里有一个程序示例来展示碰撞检测。如果检测到碰撞,图形就变为蓝色。绿色轮廓形状表示该用于计算的状态。橙色的线将未旋转圆的圆心与矩形上最近的一个点连接。你可以设置一个角度,点击按钮使其旋转。点击或者拖动某个地方使圆形移动。
设置一个角度实现圆形和矩形碰撞检测
想法很简单。为了计算方便,我们需要在矩形角度为0时,记下两个形状的位置。如果我们将矩形旋转一个角度,计算将会有一点复杂。将矩形保持0度角时候通过简单的加法就可以很容易地获得其他点的位置坐标。左上角为(x,y),右上角为(x+width, y),左下角为(x, y+height)。
这里我们不旋转矩形,而是用同样的角度旋转圆。将圆心放在矩形角度为0时的位置。单点比较容易旋转。如下简图所示,蓝色区域代表我们所看到的矩形在旋转。黑色区域用于计算。我们用0度调整形状,换言之,我们将矩形设为0度,用矩形的角度来旋转圆。
所用的公式如下所示。变量cx/cy代表圆心点,originX/originY代表旋转圆的点,x’/y’为旋转点。
x’= cos(theta) * (cx – originX) – sin(theta) * (cy – originY) + originX
y’= sin(theta) * (cx – originX) + cos(theta) * (cy – originY) + originY
找到离未旋转的圆和矩形最近的点,我们需要做的就是分别为x和y做if-else判断。
对于x,使用矩形的left x(rx)和right x(rx+width)与圆心x(cx)做比较。如果cx在rx的左边,那么rx离x最近。如果cx在rx+width的右边,那么rx+width离x最近。最后如果以上两点都不符合,那么cx本身离x最近。如下图所示,红色线表示x的位置。
对于y,与x的规则相同。如果圆心y(cy)在top y(ry)的上面,那么ry离y点最近。如果cy在bottom y(ry+height)的下面,ry+heigh离y最近。如果以上两点都不符合,那么cy离y最近。
最后,我们需要计算未旋转圆的圆心和我们所找到的最近点的距离。我使用勾股定理计算这个最近距离(a^2 + b^2 = c^2)。然后将这个值与圆的半径作比较,如果这个距离远远小于半径,那么这两个图形就会发生碰撞。
代码实例
1 2 3 4 5 6 7 8 9 10 11 | // Rotate circle's center point backdouble unrotatedCircleX = Math.cos(rect.angle) * (circle.x - rect.centerX) - Math. sin (rect.angle) * (circle.y - rect.centerY) + rect.centerX; double unrotatedCircleY = Math. sin (rect.angle) * (circle.x - rect.centerX) + Math. cos (rect.angle) * (circle.y - rect.centerY) + rect.centerY; // Closest point in the rectangle to the center of circle rotated backwards(unrotated)double closestX, closestY; // Find the unrotated closest x point from center of unrotated circleif (unrotatedCircleX < rect.x) closestX = rect.x; else if (unrotatedCircleX > rect.x + rect.width) closestX = rect.x + rect.width; else closestX = unrotatedCircleX ; // Find the unrotated closest y point from center of unrotated circleif (unrotatedCircleY < rect.y) closestY = rect.y; else if (unrotatedCircleY > rect.y + rect.height) closestY = rect.y + rect.height; else closestY = unrotatedCircleY; // Determine collisionboolean collision = false; double distance = findDistance(unrotatedCircleX , unrotatedCircleY, closestX, closestY);if (distance < circle.radius) collision = true ; // Collisionelse collision = false ; |
1 2 3 4 5 6 7 8 9 | /** * Pythagorean theorem * @param fromX * @param fromY * @param toX * @param toY */ public double findDistance( double fromX, double fromY, double toX, double toY){ double a = Math. abs (fromX - toX); double b = Math. abs (fromY - toY); return Math. sqrt ((a * a) + (b * b));} |
这篇关于圆与旋转矩形的碰撞检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!