jwoojin9
jwoojin9

Reputation: 293

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

There is a circle and a rect moving on the surface in my program. I want to know if a circle and a rect is touched to each other. It had to be very accurate. I'm sorry for not explaining its detail, but I hope you understood.

Upvotes: 2

Views: 871

Answers (1)

Rabbid76
Rabbid76

Reputation: 210890

Consider a axis aligned rectangle is given by a top left origin and a width and a height:

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

And a circle is given by a center point and a radius:

circle_cpt = (x, y)
circle_rad = r

If you want to test whether these two shapes overlap, you need to run 2 tests to capture all possible cases.

First it has to be tested if the center point of the circle is inside the rectangle. This can be done by pygame.Rect.collidepoint with ease:

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

Furthermore it has to be tested if 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])

A function which combines both tests may look like this:

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

Upvotes: 3

Related Questions