Как я могу узнать, касаются ли круг и прямоугольник в Pygame? - PullRequest
0 голосов
/ 23 февраля 2019

В моей программе круг и прямоугольник, движущиеся по поверхности.Я хочу знать, касаются ли окружность и прямоугольник друг к другу.Это должно было быть очень точным.Прошу прощения, что не объяснил детали, но надеюсь, вы поняли.

1 Ответ

0 голосов
/ 23 февраля 2019

Учтите, что выровненный по оси прямоугольник задается верхним левым началом, шириной и высотой:

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 угловая точка прямоугольника внутрикруг.Это тот случай, если расстояние между угловой точкой и центральной точкой окружности меньше или равно радиусу окружности.Точка может быть представлена ​​как pygame.math.Vector2, а расстояние между двумя точками может быть получено с помощью 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
...