找出方圆在哪一边

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 } 的两个距离将为您提供矩形的哪一侧被击中。