Quick answer: Pygame collide_mask returning wrong hits on rotated sprites? Mask is built from the original image — rebuild after rotation or rotate the mask explicitly.
Rotating a sprite via transform.rotate doesn’t rotate its mask. Collide_mask sees the un-rotated silhouette.
Mask From Surface
sprite.image = pygame.transform.rotate(orig, angle)
sprite.mask = pygame.mask.from_surface(sprite.image)
sprite.rect = sprite.image.get_rect(center=sprite.rect.center)Each rotation rebuilds the mask. Cache by angle if you spin a lot — mask.from_surface is the bottleneck otherwise.
Angle Cache
For a finite set of angles (e.g. 8 directions), pre-compute and store mask + surface per angle. Lookup at render time — zero per-frame cost.
Threshold for Anti-Aliasing
If the rotated surface has partial alpha at edges, from_surface(threshold=127) picks pixels with alpha > threshold. Stops fuzzy collisions on smooth rotations.
Verifying
Spin a sprite and ram it into another rotated sprite at various angles — collisions land where the visible pixels meet.
“Mask doesn’t rotate with image. Rebuild or cache per-angle.”
Pre-compute 36 angles (every 10°) for spinning projectiles — cheap to store, no rebuild cost in gameplay.