How to get the correct dimensions for a pygame rectangle created from an image
I have created an image's rectangle of a sprite using the command, pygame.image.get_rect()
. When locating coordinates of key points on the rectangle such as bottomleft
by drawing dots, I see that the rectangle's dimensions are completely different to the image's dimensions. In this case, the image is just the arrow head. The top right coordinate of the rectangle is correct, however the bottom left coordinate isn't.
Test to see rectangle
code to draw dots:
pygame.draw.circle(simulation_screen, red, velocity_arrow.rect.topright, 2)
pygame.draw.circle(simulation_screen,red,velocity_arrow.rect.bottomleft,2)
How can I resize the rectangle so that it fits the image?
pygame.Surface.get_rect.get_rect()
returns a rectangle with the size of the Surface object. This function does not consider the drawing area in the image. If you want to find the bounding rectangle of the painted area in the surface, you need to create a mask.
pygame.mask.from_surface
creates a pygame.mask.Mask
object form a pygame.Surface
.
A Surface is bitmap. A Mask is an 2 dimensional array with Boolean values. The Mask created is the size of the _Surface. A field is True
if the corresponding pixel in the surface is not transparent, and False
if it is transparent:
surf_mask = pygame.mask.from_surface(surf)
Get a list containing a bounding rectangles (sequence of pygame.Rect
objects) for each connected component with get_bounding_rects
.pygame.mask.Mask.get_bounding_rects
creates a list of pygame.Rect
objects. Each rectangle describes a bounding area of connected pixles. If the Surface contains exactly 1 connected image, you will get exactly 1 rectangle surrounding the image:
rect_list = surf_mask.get_bounding_rects()
Create the union rectangle of the sequence of rectangles with unionall
:
surf_mask_rect = rect_list[0].unionall(rect_list)
See the example. The black rectangle is the Surface rectangle and the red rectangle is the union of the mask component rectangles:
repl.it/@Rabbid76/ImageHitbox
import pygame
def getMaskRect(surf, top = 0, left = 0):
surf_mask = pygame.mask.from_surface(surf)
rect_list = surf_mask.get_bounding_rects()
surf_mask_rect = rect_list[0].unionall(rect_list)
surf_mask_rect.move_ip(top, left)
return surf_mask_rect
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
try:
my_image = pygame.image.load('Bomb-256.png')
except:
my_image = pygame.Surface((200, 200), pygame.SRCALPHA)
pygame.draw.circle(my_image, (0, 128, 0), (60, 60), 40)
pygame.draw.circle(my_image, (0, 0, 128), (100, 150), 40)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pos = window.get_rect().center
my_image_rect = my_image.get_rect(center = pos)
my_image_mask_rect = getMaskRect(my_image, *my_image_rect.topleft)
window.fill((255, 255, 255))
window.blit(my_image, my_image_rect)
pygame.draw.rect(window, (0, 0, 0), my_image_rect, 3)
pygame.draw.rect(window, (255, 0, 0), my_image_mask_rect, 3)
pygame.display.flip()
pygame.quit()
exit()