Reputation: 293
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
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