1

So I've been trying to make a simple maze game in pygame. Currently, I'm having problems with wall collision: The current collision system I'm using is buggy and doesn't work as intended:

import pygame
import random

# mazes
mazes = [
    [
            "wwwwwwwwwwwwwwwwwwwwwww",
            "w                     w",
            "w                     D",
            "w                     D",
            "w                     w",
            "wwwwwwwwwwwwwwwwwwwwwww"
    ]
    ,
    [
            "wwwwwwwwwwwwwwwwwwwwwww",
            "w w                   w",
            "w w wwwwwwwwwwwwwwwww w",
            "w w wD              w w",
            "w w wwwwwwwwwwwwwww w w",
            "w w                 w w",
            "w wwwwwwwwwwwwwwwwwww w",
            "w                     w",
            "wwwwwwwwwwwwwwwwwwwwwww"
    ]
]

pygame.init()

# Asset and text properties
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
blue = (0, 0, 255)

# Display properties
FPS = 30
display_width = 800
display_height = int(display_width * 2 / 3)
clock = pygame.time.Clock()
block_size = display_width / 40
level = 0

def message_to_screen(msg, color, fontSize, x_axis, y_axis):
    font = pygame.font.SysFont(None, fontSize)
    screen_text = font.render(msg, True, color)
    gameDisplay.blit(screen_text, [x_axis, y_axis])


# Create a game display
gameDisplay = pygame.display.set_mode([display_width, display_height])
pygame.display.set_caption("Mazer - Use arrow keys to move")

def gameloop(): # main function
    global level
    wall_maze, door_maze = buildMaze(mazes[1])
    gameExit = False
    gameOver = False
    movementSpeed_x = 0
    movementSpeed_y = 0
    player_x = display_width / 10
    player_y = display_height / 1.2
    speed = block_size / 2

    while not gameExit: #running game loop

        while gameOver:
            gameDisplay.fill(white)
            message_to_screen("Press Q to quit",
                              red, 40, display_width / 7, display_height / 3 )
            message_to_screen("Press N for next level", red, 40,
                              display_width / 7, display_height / 3 + 40)
            pygame.display.update()
            for event in pygame.event.get():
                if event == pygame.QUIT:
                    gameExit = True
                    gameOver = False
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        gameExit = True
                        gameOver = False
                    elif event.key == pygame.K_n:
                        level += 1
                        gameOver = False
                        gameloop()


        # Event handling
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                gameExit = True

            if event.type == pygame.KEYDOWN:

        # Movement control
                if movementSpeed_y == 0:
                    if event.key == pygame.K_LEFT:
                        movementSpeed_x = -speed
                    if event.key == pygame.K_RIGHT:
                        movementSpeed_x = speed
                if movementSpeed_x == 0:
                    if event.key == pygame.K_DOWN:
                        movementSpeed_y = speed
                    if event.key == pygame.K_UP:
                        movementSpeed_y = -speed

            if event.type == pygame.KEYUP and event.type != pygame.KEYDOWN:
                if event.key == pygame.K_LEFT or event.key == pygame.K_DOWN or \
                        event.key == pygame.K_UP or event.key == pygame.K_RIGHT:
                    movementSpeed_x = 0
                    movementSpeed_y = 0

        if movementSpeed_x > 0:
            if pygame.sprite.spritecollideany(mazer, wall_maze):
                movementSpeed_x = 0
                player_x -= speed
        elif movementSpeed_x < 0:
            if pygame.sprite.spritecollideany(mazer, wall_maze):
                movementSpeed_x = 0
                player_x += speed

        if movementSpeed_y > 0:
            if pygame.sprite.spritecollideany(mazer, wall_maze):
                movementSpeed_y = 0
                player_y -= speed
        elif movementSpeed_y < 0:
            if pygame.sprite.spritecollideany(mazer, wall_maze):
                movementSpeed_y = 0
                player_y += speed

        player_x += movementSpeed_x
        player_y += movementSpeed_y
        # Movement control

        # Rendering
        gameDisplay.fill(white)
        mazer = player(block_size, player_x, player_y)
        movingSprites = pygame.sprite.Group()
        movingSprites.add(mazer)
        wall_maze.draw(gameDisplay)
        door_maze.draw(gameDisplay)
        movingSprites.draw(gameDisplay)
        pygame.display.update()

        clock.tick(FPS) # FPS tick

        if pygame.sprite.spritecollideany(mazer, door_maze):
            gameOver = True

    pygame.quit()
    quit()

class asset(pygame.sprite.Sprite):

    def __init__(self):

        pygame.sprite.Sprite.__init__(self)

class player(asset): # Class for player

    def __init__(self, size, x, y):

        # Image properties for player
        super().__init__()
        self.image = pygame.Surface([size, size])
        self.image.fill(red)
        self.rect = self.image.get_rect()

        # Player's position
        self.rect.x = x
        self.rect.y = y

class wall(asset): # Class for wall blocks

    def __init__(self, size, x , y):

        # Image properties for wall
        super().__init__()
        self.image = pygame.Surface([size, size])
        self.image.fill(black)
        self.rect = self.image.get_rect()

        # Wall's position
        self.rect.x = x
        self.rect.y = y

class door(asset):

    def __init__(self, size, x, y):

        super().__init__()
        self.image = pygame.Surface([size, size])
        self.image.fill(blue)
        self.rect = self.image.get_rect()

        self.rect.x = x
        self.rect.y = y

def buildMaze(Maze):

    wall_list = pygame.sprite.Group()
    door_list = pygame.sprite.Group()
    pos_x = display_width / 10 - block_size
    pos_y = display_height / 1.2 + block_size

    for row in Maze:
        for space in row:
            if space == "w":
                wall_maze = wall(block_size, pos_x, pos_y)
                wall_list.add(wall_maze)
            elif space == "D":
                door_maze = door(block_size, pos_x, pos_y)
                door_list.add(door_maze)
            pos_x += block_size
        pos_y -= block_size
        pos_x = display_width / 10 - block_size

    return wall_list, door_list

gameloop()

If you try to run the code and play around with the game, you'll notice that when you move toward a wall, the player will usually stay inside the wall and the control is inverted (move right when pressing left). I suspected that it has to do with how I constructed my collision detector:

    if movementSpeed_x > 0:
        if pygame.sprite.spritecollideany(mazer, wall_maze):
            movementSpeed_x = 0
            player_x -= speed
    elif movementSpeed_x < 0:
        if pygame.sprite.spritecollideany(mazer, wall_maze):
            movementSpeed_x = 0
            player_x += speed

    if movementSpeed_y > 0:
        if pygame.sprite.spritecollideany(mazer, wall_maze):
            movementSpeed_y = 0
            player_y -= speed
    elif movementSpeed_y < 0:
        if pygame.sprite.spritecollideany(mazer, wall_maze):
            movementSpeed_y = 0
            player_y += speed

One more thing, I thought that by having this code before pygame.display.update(), it wouldn't show the player hitting the wall because the position is supposed to be updated before that but somehow it doesn't work as intended. Thank you for looking at my code.

ProfNero
  • 11
  • 2
  • That is WAY too much code in your question buddy. No one wants to spend so much time going through this code. Please concise it to the bare minimum needed to understand your question. – Rann Lifshitz Apr 14 '18 at 07:48
  • @RannLifshitz Thank you, I'll try to do that. – ProfNero Apr 14 '18 at 07:51
  • Better use the rects of the involved sprites to reset the position of the player. Here's an example: https://stackoverflow.com/a/45017561/6220679 – skrx Apr 14 '18 at 07:54

0 Answers0