Once your objects are sprites in groups, one function call checks a sprite against a whole group. This game has a ship that shoots lasers at a row of enemies:
Press Play, click the game, move with the arrow keys and shoot with Space. groupcollide(lasers, enemies, True, True) finds every laser touching an enemy and removes both.
The collision functions
| Function | Returns |
|---|---|
spritecollide(sprite, group, dokill) | List of sprites in group that touch sprite |
spritecollideany(sprite, group) | The first sprite that touches, or None (fastest when you only need yes or no) |
groupcollide(group1, group2, dokill1, dokill2) | Dict: each sprite of group1 that hit, to the list of group2 sprites it hit |
collide_rect(a, b) | True if the rects overlap (the default test) |
collide_circle(a, b) | True if circles around the sprites overlap |
collide_mask(a, b) | True if their visible pixels overlap |
dokill=True removes the sprites that collided from all their groups, which is what you want for coins and bullets. Use False when the sprite should stay, such as a wall or the player.
Every collide function takes an optional last argument, collided, which picks the test:
pygame.sprite.spritecollide(player, enemies, False, pygame.sprite.collide_circle)
Pixel-perfect collisions with masks
Rect collisions count the transparent corners of an image, so a round enemy "hits" before it visibly touches. A mask records which pixels of an image are solid, and collide_mask compares those:
Move the spike ball toward the ghost with the arrow keys. The outlines turn yellow as soon as the rectangles overlap; the background turns red only when real pixels touch.
Set self.mask once in __init__: collide_mask uses it if it exists, and otherwise builds a new mask on every check, which is slow. Rebuild it only when the image changes. Masks cost more than rects, so a common pattern is a cheap spritecollideany first, then the mask test only on the sprites it found.
Frequently Asked Questions
How do I check collisions between a sprite and a group?
hits = pygame.sprite.spritecollide(player, enemies, False) returns the list of sprites in enemies whose rects overlap the player's. Pass True instead of False to remove them from their groups as well.
How do I check collisions between two groups?
pygame.sprite.groupcollide(bullets, enemies, True, True) returns a dictionary of each bullet that hit to the enemies it hit. The two booleans say whether to kill the sprites of each group.
How do I make pixel-perfect collisions?
Pass collided=pygame.sprite.collide_mask to spritecollide. It compares the sprites' visible pixels instead of their rectangles. Give each sprite a self.mask = pygame.mask.from_surface(self.image) so the mask is not rebuilt on every check.