This is the first time I try to use mask collisions and can't find reference for this specific situation (polygon and sprite mask collision).
I want the capability for sprites to detect other sprites using a 'field-of-view' method. Here, is an example of my Pygame application:
A bunch of worms with their FOV shown for debugging. In this scenario, I want them to see the little green dots. Firstly, I can generate that fov as a polygon. I draw it on the pygame.display Surface (referred to as program.screen). Then, I check each 'target' in the sprite group and check for rect collision between the polygon and the target - works fine. So all the math and calculations are correct, but I cannot get the next bit with mask to mask collision to work. With the code I attach, the print("Detection") statement is never called.
#Check if entity can detect its target given its fov
#
#@param entity: pygame.sprite.Sprite object performing the look() function
#@param fov: The angle and depth of view of 'entity', in the form of [angle (degrees), depth (pixels)]
#@param target: pygame.sprite.Sprite object the 'entity' is looking out for
#@param program: the main instance that runs and handles the entire application
def look(entity, fov, target, program):
r = fov[1] * np.cos(np.pi / 180 * fov[0])
coords_1 = (r * np.sin(entity.rot * np.pi / 180) + entity.x, r * np.cos(entity.rot * np.pi / 180) + entity.y)
coords_2 = (r * np.sin((entity.rot + 2*fov[0]) * np.pi / 180) + entity.x, r * np.cos((entity.rot + 2*fov[0]) * np.pi / 180) + entity.y)
poly_coords = ((entity.x, entity.y), coords_1, coords_2) # The coordinates of the fov
view = pygame.draw.polygon(program.screen, WHITE, poly_coords) # Draw the fov white for indication
pygame.display.update(view)
# Iterate over all sprites
for i in program.all_sprites:
if isinstance(i, target):
# Rough check for if this item is colliding with the fov polygon
if view.colliderect(i.rect):
# Exact check if this item is roughly colliding with the fov polygon
mask = pygame.mask.from_surface(i.image)
if pygame.mask.from_surface(program.screen).overlap(mask, (0, 0)):
# For now, colour the polygon red as indication
signal = pygame.draw.polygon(program.screen, RED, [(entity.x, entity.y), coords_1, coords_2])
print("Detection")
pygame.display.update(signal)
When I use
if pygame.sprite.collide_mask(mask, pygame.mask.from_surface(program.screen)):
for the mask check, I get an
AttributeError: 'pygame.mask.Mask' object has no attribute 'rect'
I also tried to draw the polygon on a different surface with the same result as the first code (no detection):
def look(entity, fov, target, program):
r = fov[1] * np.cos(np.pi / 180 * fov[0])
coords_1 = (r * np.sin(entity.rot * np.pi / 180) + entity.x, r * np.cos(entity.rot * np.pi / 180) + entity.y)
coords_2 = (r * np.sin((entity.rot + 2*fov[0]) * np.pi / 180) + entity.x, r * np.cos((entity.rot + 2*fov[0]) * np.pi / 180) + entity.y)
poly_coords = ((entity.x, entity.y), coords_1, coords_2) # The coordinates of the fov
view_layer = pygame.Surface((500, 500)) # some random size big enough to hold the fov
#view_layer.fill(BLUE)
view = pygame.draw.polygon(view_layer, WHITE, poly_coords) # Draw the fov white for indication
pygame.display.update(view)
program.screen.blit(view_layer, (min(poly_coords[0]), max(poly_coords[1])))
pygame.display.update(view)
# Iterate over all sprites
for i in program.all_sprites:
if isinstance(i, target):
# Rough check for if this item is colliding with the fov polygon
if view.colliderect(i.rect):
# Exact check if this item is roughly colliding with the fov polygon
mask = pygame.mask.from_surface(i.image)
if pygame.mask.from_surface(view_layer).overlap(mask, (0, 0)):
# For now, colour the polygon red as indication
signal = pygame.draw.polygon(program.screen, RED, [(entity.x, entity.y), coords_1, coords_2])
print("Detection")
pygame.display.update(signal)
What is wrong with the ways I'm trying to do it, or is there a better way for doing it?
Thanks, Kres