我如何知道 Pygame 中是否触摸了圆圈和矩形?

How can I know if a circle and a rect is touched in Pygame?

在我的程序中有一个圆和一个矩形在表面上移动。我想知道一个圆和一个矩形是否相互接触。它必须非常准确。很抱歉没有解释它的细节,但我希望你能理解。

考虑一个轴对齐的矩形由左上原点以及宽度和高度给出:

rect_tl   = (x, y)
rect_size = (width, height)

圆由圆心和半径给出:

circle_cpt = (x, y)
circle_rad = r

如果你想测试这两个形状是否重叠,你需要运行 2个测试来捕获所有可能的情况。

首先要判断圆心是否在矩形内部。这可以通过 pygame.Rect.collidepoint 轻松完成:

rect = pygame.Rect(*rect_tl, *rect_size)
isIsect = rect.collidepoint(*circle_cpt)

此外还需要测试如果any corner point of the rectangle is inside the circle. This is the case if the distance between a corner point and the center point of the circle is less than is or equal the radius of the circle. A point can be represented by pygame.math.Vector2 and the distance between 2 points can be get by pygame.math.Vector2.distance_to():

centerPt = pygame.math.Vector2(*circle_cpt)
cornerPts = [rect.bottomleft, rect.bottomright, rect.topleft, rect.topright]
isIsect = any([p for p in cornerPts if pygame.math.Vector2(*p).distance_to(centerPt) <= circle_rad])

结合这两个测试的函数可能如下所示:

def isectRectCircle(rect_tl, rect_size, circle_cpt, circle_rad):

    rect = pygame.Rect(*rect_tl, *rect_size)
    if rect.collidepoint(*circle_cpt):
        return True

    centerPt = pygame.math.Vector2(*circle_cpt)
    cornerPts = [rect.bottomleft, rect.bottomright, rect.topleft, rect.topright]
    if [p for p in cornerPts if pygame.math.Vector2(*p).distance_to(centerPt) <= circle_rad]:
        return True

    return False