找出方圆在哪一边
Find which side of square circle is on
我正在我的 2D 游戏中构建一些碰撞检测,并且我有一个方法来测试碰撞并找到碰撞的深度和法线,但我一直在试图找出哪个一侧发生碰撞。
这里的CirclePosition和RectPosition就是形状的中心。我正在使用 OpenGL,因此正 Y = 向下和负 Y = 向上。
我测试的对象是一个圆形和一个方形。这些形状是轴对齐的。
所以我的问题是:
如何检测圆圈击中了正方形的哪一侧?
这是我目前的代码:
enum side {
SideLeft,
SideRight,
SideAbove,
SideBelow,
};
typedef struct {
int Collided;
float Depth;
float2 Normal;
side Side;
} collision;
collision CircleRectIntersection(float2 CirclePosition, float Radius, float2 RectPosition, float2 Size) {
float Top = RectPosition.Y - (Size.Y / 2);
float Left = RectPosition.X - (Size.X / 2);
float Bottom = RectPosition.Y + (Size.Y / 2);
float Right = RectPosition.X + (Size.X / 2);
float ExtentX = Size.X / 2;
float ExtentY = Size.Y / 2;
float2 N = RectPosition - CirclePosition;
float2 Closest = N;
Closest.X = Clamp(-ExtentX, ExtentX, Closest.X);
Closest.Y = Clamp(-ExtentY, ExtentY, Closest.Y);
bool Inside = false;
if(N == Closest) {
Inside = true;
if(fabs(N.X) > fabs(N.Y)) {
if(Closest.X > 0) Closest.X = ExtentX;
else Closest.X = -ExtentX;
}
else {
if(Closest.Y > 0) Closest.Y = ExtentY;
else Closest.Y = -ExtentY;
}
}
float2 Normal = N - Closest;
float D = LengthSquare(Normal);
float R = Radius;
D = sqrt(D);
collision C;
if(D > R && !Inside) {
C.Collided = 0;
return C;
}
if(Inside) C.Normal = -N;
else C.Normal = N;
C.Depth = R - D;
return C;
}
下面是一些我希望它如何工作的示例代码:
int main(int argc, char **argv) {
float2 RectPosition = float2(100, 100);
float2 RectSize = float2(100, 100);
float2 CirclePosition = float2(150, 100);
float2 Radius = 20.0f;
collision C = CircleRectIntersection(CirclePosition, Radius, RectPosition, RectSize);
// here I would expect C.Side to be side.Right, as the circle is to the right of the rect
}
四个距离中的最小值,从 CirclePosition.X
到 { Left, Right } 的两个距离和从 CirclePosition.Y
到 { Top, Bottom } 的两个距离将为您提供矩形的哪一侧被击中。
我正在我的 2D 游戏中构建一些碰撞检测,并且我有一个方法来测试碰撞并找到碰撞的深度和法线,但我一直在试图找出哪个一侧发生碰撞。
这里的CirclePosition和RectPosition就是形状的中心。我正在使用 OpenGL,因此正 Y = 向下和负 Y = 向上。
我测试的对象是一个圆形和一个方形。这些形状是轴对齐的。
所以我的问题是:
如何检测圆圈击中了正方形的哪一侧?
这是我目前的代码:
enum side {
SideLeft,
SideRight,
SideAbove,
SideBelow,
};
typedef struct {
int Collided;
float Depth;
float2 Normal;
side Side;
} collision;
collision CircleRectIntersection(float2 CirclePosition, float Radius, float2 RectPosition, float2 Size) {
float Top = RectPosition.Y - (Size.Y / 2);
float Left = RectPosition.X - (Size.X / 2);
float Bottom = RectPosition.Y + (Size.Y / 2);
float Right = RectPosition.X + (Size.X / 2);
float ExtentX = Size.X / 2;
float ExtentY = Size.Y / 2;
float2 N = RectPosition - CirclePosition;
float2 Closest = N;
Closest.X = Clamp(-ExtentX, ExtentX, Closest.X);
Closest.Y = Clamp(-ExtentY, ExtentY, Closest.Y);
bool Inside = false;
if(N == Closest) {
Inside = true;
if(fabs(N.X) > fabs(N.Y)) {
if(Closest.X > 0) Closest.X = ExtentX;
else Closest.X = -ExtentX;
}
else {
if(Closest.Y > 0) Closest.Y = ExtentY;
else Closest.Y = -ExtentY;
}
}
float2 Normal = N - Closest;
float D = LengthSquare(Normal);
float R = Radius;
D = sqrt(D);
collision C;
if(D > R && !Inside) {
C.Collided = 0;
return C;
}
if(Inside) C.Normal = -N;
else C.Normal = N;
C.Depth = R - D;
return C;
}
下面是一些我希望它如何工作的示例代码:
int main(int argc, char **argv) {
float2 RectPosition = float2(100, 100);
float2 RectSize = float2(100, 100);
float2 CirclePosition = float2(150, 100);
float2 Radius = 20.0f;
collision C = CircleRectIntersection(CirclePosition, Radius, RectPosition, RectSize);
// here I would expect C.Side to be side.Right, as the circle is to the right of the rect
}
四个距离中的最小值,从 CirclePosition.X
到 { Left, Right } 的两个距离和从 CirclePosition.Y
到 { Top, Bottom } 的两个距离将为您提供矩形的哪一侧被击中。