I am using Pygame and have an image. I can clip a rectangle from it:
image = pygame.transform.scale(pygame.image.load('example.png'), (32, 32))
handle_surface = image.copy()
handle_surface.set_clip(pygame.Rect(0, 0, 32, 16))
clipped_image = surface.subsurface(handle_surface.get_clip())
I have tried to use subsurface
by passing a Surface
:
handle_surface = image.copy()
hole = pygame.Surface((32, 32))
pygame.draw.circle(hole, (255, 255, 255), (0, 0), 32)
handle_surface.set_clip(hole)
image = surface.subsurface(handle_surface.get_clip())
surf = image.copy()
But I get the error:
ValueError: invalid rectstyle object
This error is because despite its name, subsurface
expects a Rect
, not a Surface
. Is there a way to clip another shape from this image and have collidepoint
work correctly?
CodePudding user response:
You cannot use pygame.Surface.subsurface
because a Surface is always rectangular and cannot have a circular shape. pygame.Rect.collidepoint
detects if a point is inside a rectangular area and therefore cannot help you either.
Collision detection between a circle and a point can be calculated using the distance between the pointer and the center of the circle. Calculate the square of the Euclidean distance (dx*dx dy*dy
) from the point to the center of the circle. Check that the square of the distance is less than the square of the radius. In the following code the coordinates of the point are (px
, py
) and the circle is defined by its center (cx, cy
) and its radius (radius
).
dx = px - cx
dy = py - cy
if dx*dx dy*dy <= radius*radius:
print('hit')
An alternative solution could be PyGame collision with masks. Also pygame.sprite.collide_circle
could help, but then you would have to create a pygame.sprite.Sprite
object for the point with radius 1, which seems to overcomplicate the problem.
If you want to clip a circular area from a pygame.Surface
, see:
- how to make circular surface in PyGame
- How do I focus light or how do I only draw certain circular parts of the window in pygame?
- How do I display a large black rectangle with a moveable transparent circle in pygame?
- Can I use an image on a moving object within Pygame as opposed to to a color?
Short instruction:
- Create a rectangular partial area from the image (only if the circle does not fill the whole image). However, the image must have an alpha channel. If it does not have one, this can be achieved with
convert_alpha
. - Create a transparent (
pygame.SRCALPHA
) mask with the size of the image - Draw a white opaque circle on the mask (I use
pygame.draw.ellipse
here, because it is easier to set the dimension) - Blend the circular mask with the image using the blend mode
pygame.BLEND_RGBA_MIN
. (seepygame.Surface.blit
)
sub_image = image.subsurface(pygame.Rect(x, y, w, h)).convert_alpha()
mask_image = pygame.Surface(sub_image.get_size(), pygame.SRCALPHA)
pygame.draw.ellipse(mask_image, (255, 255, 255, 255), sub_image.get_rect())
sub_image.blit(mask_image, (0, 0), special_flags=pygame.BLEND_RGBA_MIN)