Ensure that the Player
object is positioned in the center of cell of the grid
. e.g. calculate a random position for the player
:
def load_player(background):
pimg = pygame.Surface((10, 10))
pimg.fill((200, 20, 20))
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
return Player(pimg, (px, py), background)
To track the player, but highlight the player position, the current player position has to be tint in a different color, before the player is updated and is redrawn:
pygame.draw.rect(screen, (255, 164, 164), player.rect)
sprites.update(None, dt)
sprites.draw(screen)
For the collision test:
- The current position of the player in the
grid
has to be identified. - The new possible new position of the player, dependent on the movement has to be identified.
- If a wall is on the track from the current to the new position, then the movement has to be skipped
class Player(pygame.sprite.Sprite):
def __init__(self, image, pos, background):
super().__init__()
self.image = image
self.pos = pygame.Vector2(pos)
self.rect = self.image.get_rect(center=self.pos)
self.background = background
def update(self, events, dt):
pressed = pygame.key.get_pressed()
move = pygame.Vector2((0, 0))
# calculate maximum movement and current cell position
testdist = dt // 5 + 2
cellx = self.rect.centerx // width
celly = self.rect.centery // width
minx = self.rect.left // width
maxx = self.rect.right // width
miny = self.rect.top // width
maxy = self.rect.bottom // width
# test move up
if minx == maxx and pressed[pygame.K_w]:
nexty = (self.rect.top-testdist) // width
if celly == nexty or (nexty >= 0 and not grid[celly][cellx].walls[0]):
move += (0, -1)
# test move right
elif miny == maxy and pressed[pygame.K_d]:
nextx = (self.rect.right+testdist) // width
if cellx == nextx or (nextx < cols and not grid[celly][cellx].walls[1]):
move += (1, 0)
# test move down
elif minx == maxx and pressed[pygame.K_s]:
nexty = (self.rect.bottom+testdist) // width
if celly == nexty or (nexty < rows and not grid[celly][cellx].walls[2]):
move += (0, 1)
# test move left
elif miny == maxy and pressed[pygame.K_a]:
nextx = (self.rect.left-testdist) // width
if cellx == nextx or (nextx >= 0 and not grid[celly][cellx].walls[3]):
move += (-1, 0)
self.pos = self.pos + move*(dt/5)
self.rect.center = self.pos
If you want to restart the maze, the you’ve to get rid of the nested game loops. Use 1 game loop and a condition, which state if the game is in play
state or initializing the maze.
To check if the player has reached the goal can be done by pygame.Rect.colliderect()
:
finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)
To restart you’ve to reset the grid
:
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
Set the player to a new random position:
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
player.pos = pygame.Vector2(px, py)
player.rect = player.image.get_rect(center=player.pos)
Clear the background and reset the state play
:
screen.fill(0)
play = False
Full main
code:
def main():
global current_cell, grid
player = None
initialized = False
current_maze = None
dt = 0
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
sprites = pygame.sprite.Group()
if not initialized:
#current_maze = 0
background = load_background()
background = None
player = load_player(background)
sprites.add(player)
initialized = True
play = False
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if play == True:
pygame.draw.rect(screen, (255, 164, 164), player.rect)
sprites.update(None, dt)
sprites.draw(screen)
dt = clock.tick(60)
finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)
if finished:
# init new grid
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
# create new random player positon
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
player.pos = pygame.Vector2(px, py)
player.rect = player.image.get_rect(center=player.pos)
# clear screen
screen.fill(0)
play = False
else:
current_cell.visited = True
current_cell.current = True
next_cell = current_cell.checkNeighbors()
if next_cell != False:
current_cell.neighbors = []
stack.append(current_cell)
removeWalls(current_cell,next_cell)
current_cell.current = False
current_cell = next_cell
elif len(stack) > 0:
current_cell.current = False
current_cell = stack.pop()
else:
play = True
for y in range(rows):
for x in range(cols):
grid[y][x].draw()
pygame.display.flip()
see also How do I prevent the player from moving through the walls in a maze?