This is an interesting question. It's possible to do this with a huge sprite representing the maze, using a sprite mask to ensure only the walls are part of collision. I'm not sure that's a good way to go, but it is relatively simple.
When the sprite is created, you must be sure to create the mask:
self.image = pygame.image.load( maze_image ).convert_alpha()
self.mask = pygame.mask.from_surface( self.image )
Then when the collision is checked, you must also ensure it's using the mask. This I must admit, left me a bit confused. I was under the impression that if a sprite has a .mask
member it was always used for collisions. Perhaps it's just the function pygame.sprite.spritecollide()
that doesn't use it automatically, since it does have the optional 'collided' parameter. /me shrugs.
Anyway, this leads to the collision call:
if ( pygame.sprite.spritecollide( maze, alien_group, False, collided=pygame.sprite.collide_mask ) ):
Where maze
is the Maze sprite, and alien_group
is a sprite GroupSingle
containing only the single Player's alien sprite. The aforementioned extra parameter to force with-mask collisions is last. This collision function returns a list of what's collided with the maze
sprite, but given there's only one alien, there's no need to check with what. The list can only be empty, or contain the alien.
The game checks for collision, and if found, changes the window background colour to red. Probably in your code, it needs to block the player, or whatever.

green_alien.png

hexmaze.png (has a transparent background)

Reference Code:
import pygame
# Window size
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 690
FPS = 60
# background colours
INKY_BLACK = ( 0, 0, 0 )
FIREY_RED = ( 203, 49, 7 )
class MazeSprite( pygame.sprite.Sprite ):
""" A maze with a transparent background as a *huge* sprite """
def __init__( self, maze_image ):
pygame.sprite.Sprite.__init__( self )
self.image = pygame.image.load( maze_image ).convert_alpha()
self.mask = pygame.mask.from_surface( self.image )
self.rect = self.image.get_rect( topleft=(0,0) )
class AlienSprite( pygame.sprite.Sprite ):
""" A tiny little alien hoardette """
def __init__( self, alien_image , x=50, y=50 ):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load( alien_image ).convert_alpha()
self.mask = pygame.mask.from_surface( self.image )
self.rect = self.image.get_rect( center=( x, y ) )
def moveBy( self, dx, dy ):
self.rect.move_ip( dx, dy )
#print("Now at %s" % ( str( self.rect.center ) ) )
### MAIN
pygame.init()
pygame.font.init()
SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE )
pygame.display.set_caption("Maze Sprite-Collision Example")
# Make some sprites to hold the Maze background and Player's Alien
maze = MazeSprite( 'hexmaze.png' )
alien = AlienSprite( "green_alien.png", 283, 155 )
sprite_group = pygame.sprite.Group() # All sprites for updating and drawing
sprite_group.add( maze )
sprite_group.add( alien )
alien_group = pygame.sprite.GroupSingle() # Just for the alien collisions
alien_group.add( alien )
clock = pygame.time.Clock()
done = False
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
# Handle continuous-keypresses
keys = pygame.key.get_pressed()
if ( keys[pygame.K_UP] ):
alien.moveBy( 0, -1 )
elif ( keys[pygame.K_DOWN] ):
alien.moveBy( 0, 1 )
elif ( keys[pygame.K_LEFT] ):
alien.moveBy( -1, 0 )
elif ( keys[pygame.K_RIGHT] ):
alien.moveBy( 1, 0 )
# has the alien hit the walls?
background = INKY_BLACK
# NOTE: Ensure we use "mask" collision
# It's not used (here) automatically
if ( pygame.sprite.spritecollide( maze, alien_group, False, collided=pygame.sprite.collide_mask ) ):
# returned list is not empty
background = FIREY_RED
# Repaint the screen
sprite_group.update() # re-position the game sprites
window.fill( background )
sprite_group.draw( window ) # draw the game sprites
pygame.display.flip()
clock.tick_busy_loop( FPS )
pygame.quit()