PacMan Movement in Maze

Viewed 22

I am recreating PacMan game, right now my code just gets the key arrow pressed whether LRUD and moves in that direction, what I want is for the PacMan to move smoothly between the maze just like my Ghost is. Is there any way to make it move strictly left meaning if there is a wall on top and bottom, I don't want it to move slighty up or slightly down, just in that direction or turn around and go right. So it starts off at (225, 176) position on the screen, what I tried is to get the values for which % 25 == 0, then stop it from moving, but I'm not sure that's always the case. Is there a better way to make it move in one direction always?

class Maze():
    def __init__(self):
        self.Pellets = []
        self.Walls = []
        self.Energizer = []
        self.Ghosts = []
        self.BlockWidth = 25
        self.BlockHeight = 25
        self.MazeOffsetX = 0
        self.MazeOffsetY = 50
        # 0 - Pellets
        # 1 - Walls
        # 2 - Empty Spaces
        # 3 - Energizers
        # 4 - Ghosts
        self.Matrix = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], \
                      [1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
                      [1,3,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,3,1], \
                      [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
                      [1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1], \
                      [1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
                      [1,1,1,1,0,1,1,1,2,1,2,1,1,1,0,1,1,1,1], \
                      [2,2,2,1,0,1,2,2,2,4,2,2,2,1,0,1,2,2,2], \
                      [1,1,1,1,0,1,2,1,1,1,1,1,2,1,0,1,1,1,1], \
                      [2,2,2,2,0,2,2,1,4,4,4,1,2,2,0,2,2,2,2], \
                      [1,1,1,1,0,1,2,1,1,1,1,1,2,1,0,1,1,1,1], \
                      [2,2,2,1,0,1,2,2,2,2,2,2,2,1,0,1,2,2,2], \
                      [1,1,1,1,0,1,2,1,1,1,1,1,2,1,0,1,1,1,1], \
                      [1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], \
                      [1,3,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,3,1], \
                      [1,0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,1], \
                      [1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1], \
                      [1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1], \
                      [1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1], \
                      [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], \
                      [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
        
        # BackgroundImage(X, Y, WIDTH, HEIGHT)
        self.MazeX = self.BlockWidth * (len(self.Matrix[0]) 
                      + self.MazeOffsetX)
        self.MazeY = self.BlockHeight * (len(self.Matrix)
                      + self.MazeOffsetY)
        self.MazeWidth = self.BlockWidth * len(self.Matrix[0])
        self.MazeHeight = self.BlockHeight * len(self.Matrix) 

    def DrawMaze(self, MazeSurface):
        for Row in range(len(self.Matrix)):
            for Column in range(len(self.Matrix[0])):
                # Saves the position of each pellet
                if self.Matrix[Row][Column] == 0:
                    self.Pellets.append([self.BlockWidth * Column,
                                         self.BlockHeight * Row, 4, 4])
                    if self.Matrix[Row][Column - 1] != 1 and \
                       self.Matrix[Row][Column - 1] != 2:
                        self.Pellets.append([((self.BlockWidth * Column) - 13),
                                           self.BlockHeight * Row , 4, 4])
                    if Column + 1 == None and Row - 1 == None:
                        if self.Matrix[Row][Column + 1] != 1 and \
                           self.Matrix[Row][Column + 1] != 2:
                            self.Pellets.append([((self.BlockWidth * Column) + 13),
                                               self.BlockHeight * Row, 4, 4])
                        if self.Matrix[Row - 1][Column] != 1 and \
                           self.Matrix[Row - 1][Column] != 2:
                            self.Pellets.append([self.BlockWidth * Column,
                                               ((self.BlockHeight * Row) - 13),
                                               4, 4])
                    if self.Matrix[Row + 1][Column] != 1 and \
                       self.Matrix[Row + 1][Column] != 2:
                        self.Pellets.append([self.BlockWidth * Column,
                                           ((self.BlockHeight * Row) + 13), 
                                           4, 4])
                # Saves the position of each wall
                if self.Matrix[Row][Column] == 1:
                    self.Walls.append(pygame.draw.rect(MazeSurface, WHITE,
                                     [((self.BlockWidth) * Column),
                                      ((self.BlockHeight) * Row), 
                                        self.BlockWidth, self.BlockHeight]))
                # Saves the position of each Energizer
                if self.Matrix[Row][Column] == 3:
                    self.Energizer.append([(self.BlockWidth * Column),
                                           (self.BlockHeight * Row), 14, 14])
                # Saves the position of each Ghost
                if self.Matrix[Row][Column] == 4:
                    self.Ghosts.append([(self.BlockWidth * Column), 
                                        (self.BlockHeight * Row), 23, 23])
 
class PacMan(Maze):
    def __init__(self):
        Maze.__init__(self)
        self.PacManStartSurface = pygame.transform.scale(
                                  pygame.image.load(
                                  os.path.join("Pac Man", "PacManStart.png"))
                                  .convert_alpha(), (23, 23))
        self.PacManStartRect = pygame.Rect((225, 376, 23, 23))
        self.PacManSurface = pygame.transform.scale(
                             pygame.image.load(
                             os.path.join("Pac Man", "PacManRight.png"))
                             .convert_alpha(), (23, 23))
        self.PacManRect = pygame.Rect((225, 376, 23, 23))
        self.CurrentSurface = self.PacManSurface
        self.CurrentRect = self.PacManRect
        self.MouthOpen = False
        self.LastBiteTime = time.time()
        self.PacManDirection = ""
        self.TimeBetweenBites = 0.1
        self.Lives = 3

    def PacManMovement(self):
        key = pygame.key.get_pressed()
        if key[pygame.K_LEFT]:
            self.PacManDirection = "LEFT"
        elif key[pygame.K_RIGHT]:
            self.PacManDirection = "RIGHT"
        elif key[pygame.K_UP]:
            self.PacManDirection = "UP"
        elif key[pygame.K_DOWN]:
            self.PacManDirection = "DOWN"
        
    def ContinuePacManMovement(self):
        if self.PacManDirection == "LEFT":
            self.CurrentRect.move(-SPEED, 0)
            self.PacManWallDetection(-1, 0)
        if self.PacManDirection == "RIGHT":
            self.CurrentRect.move(SPEED, 0)
            self.PacManWallDetection(1, 0)
        if self.PacManDirection == "UP":
            self.CurrentRect.move(0, -SPEED)
            self.PacManWallDetection(0, -1)
        if self.PacManDirection == "DOWN":
            self.CurrentRect.move(0, SPEED)
            self.PacManWallDetection(0, 1)

    def PacManTeleport(self):
        if self.CurrentRect.x < 0:
            self.CurrentRect.right = SCREEN_WIDTH + 20
        if self.CurrentRect.x > SCREEN_WIDTH:
            self.CurrentRect.x = 0
            
    def PacManWallDetection(self, x, y):
        self.CurrentRect.right += x
        for Wall in self.Walls:
            Collide = self.CurrentRect.colliderect(Wall)
            if Collide:
                if x < 0: 
                    self.CurrentRect.left = Wall.right
                if x > 0:
                    self.CurrentRect.right = Wall.left
                break
        
        self.CurrentRect.top += y
        for Wall in self.Walls:
            Collide = self.CurrentRect.colliderect(Wall)
            if Collide:
                if y < 0:
                    self.CurrentRect.top = Wall.bottom
                if y > 0:
                    self.CurrentRect.bottom = Wall.top
                break
            
    def EatPellets(self):
        for Row in range(len(self.Matrix)):
            for Column in range(len(self.Matrix[0])):
                for Pellet in self.Pellets:
                    if Pellet[0] < self.CurrentRect.x + Pellet[2] and \
                       Pellet[0] + self.CurrentRect.width > self.CurrentRect.x and \
                       Pellet[1] < self.CurrentRect.y + Pellet[3] and \
                       self.CurrentRect.height + Pellet[1] > self.CurrentRect.y:
                        Chomp = self.CurrentRect.colliderect(Pellet)
                        if Chomp:
                            Main.PlaySound(0)
                            self.Pellets.remove(Pellet)
                            self.Matrix[Row][Column] = 2
                            self.Score += 10
        if self.Score > self.HighScore:
            self.HighScore = self.Score
        return str(self.Score), str(self.HighScore)
    
    def EatEnergizer(self):
        for Row in range(len(self.Matrix)):
            for Column in range(len(self.Matrix[0])):
                for PowerUp in self.Energizer:
                    Chomp = self.CurrentRect.colliderect(PowerUp)
                    if Chomp:
                        self.Energizer.remove(PowerUp)
                        #self.Matrix[Row][Column] = 3
                        self.Score += 50
                        Main.PlaySound(1)
        if self.Score > self.HighScore:
            self.HighScore = self.Score
        return str(self.Score), str(self.HighScore)
    
    def EatGhosts(self):
        pass
    
    def PacManAnimation(self):
        if time.time() - self.LastBiteTime >= self.TimeBetweenBites:
           self.LastBiteTime = time.time()
           if self.MouthOpen:
               self.CurrentSurface = self.PacManStartSurface
           else:
               self.CurrentSurface = self.PacManSurface
           self.MouthOpen = not self.MouthOpen
           if self.PacManDirection == "LEFT":
               self.CurrentSurface = pygame.transform.rotate(
                                     self.CurrentSurface, 180)
           if self.PacManDirection == "RIGHT":
               self.CurrentSurface = self.CurrentSurface
           if self.PacManDirection == "UP":
               self.CurrentSurface = pygame.transform.rotate(
                                     self.CurrentSurface, 90)
           if self.PacManDirection == "DOWN":
               self.CurrentSurface = pygame.transform.rotate(
                                     self.CurrentSurface, 270)
               
    def DrawPacMan(self):
        MazeSurface.blit(self.CurrentSurface, self.CurrentRect)

class Main():
    def __init__(self):
        # Inherits Maze class
        Maze.__init__(self)
        PacMan.__init__(self)
        PinkGhost.__init__(self)
        YellowGhost.__init__(self)
        BlueGhost.__init__(self)
        RedGhost.__init__(self)
        self.Score = 0
        self.HighScore = 0
    
    def DrawLives(self):
        PacManSurface = self.PacManSurface
        PacManSurface = pygame.transform.rotate(PacManSurface, 180)
        PacManLife1 = PacManSurface.get_rect(center = 
                                            ((SCREEN_WIDTH - 370) // 2, 
                                            SCREEN_HEIGHT - 17))
        PacManLife2 = PacManSurface.get_rect(center = 
                                            ((SCREEN_WIDTH - 310) // 2, 
                                            SCREEN_HEIGHT - 17))
        PacManLife3 = PacManSurface.get_rect(center = 
                                            ((SCREEN_WIDTH - 250) // 2,
                                            SCREEN_HEIGHT - 17))
        SCREEN.blit(PacManSurface, PacManLife1)
        SCREEN.blit(PacManSurface, PacManLife2)
        SCREEN.blit(PacManSurface, PacManLife3)
        
    def DrawPellets(self):
        for Position in self.Pellets:
            X = Position[0] + 13
            Y = Position[1] + 13
            Width = Position[2] // 2
            Height = Position[3] // 2
            pygame.draw.circle(MazeSurface, PEACH, (X, Y), Width, Height)
        
    def DrawEnergizers(self):
        for Position in self.Energizer:
            X = Position[0] + 13
            Y = Position[1] + 20
            Width = Position[2] // 2
            Height = Position[3] // 2
            pygame.draw.circle(MazeSurface, PEACH, (X, Y), Width, Height)
        
    def DrawBackground(self):
        MazeSurface.blit(BackgroundSurface, BackgroundRect) 
        
    def PlaySound(self, Track):
        if Track == 0:
            Eat = pygame.mixer.Sound(
                  os.path.join("Sound Effects", "pacman_chomp.wav"))
            Eat.play()
            pygame.mixer.fadeout(400)
        if Track == 1:
            EatPellet = pygame.mixer.Sound(
                        os.path.join("Sound Effects", "pacman_eatghost.wav"))
            EatPellet.play()
            pygame.mixer.music.play(7)
            pygame.mixer.fadeout(400)
            
    def GameOver(self):
        if self.Lives == 0:
            print("Game Over")
                
    def ShowScore(self):
        global Font
        OneUpText = Font.render("1UP", True, WHITE)
        OneUpTextRect = OneUpText.get_rect(center = (70, 10))
        # Displays current score
        OneUpScoreText = Font.render(str(self.Score), True, WHITE)
        OneUpScoreRect = OneUpScoreText.get_rect(center =
                                                ((SCREEN_WIDTH - 290) 
                                                // 2, 26))
        HighScoreText = Font.render("High Score", True, WHITE)
        HighScoreTextRect = HighScoreText.get_rect(center = 
                                                  (SCREEN_WIDTH // 2, 10))
        # Displays High Score
        HighScoreNumber = Font.render(str(self.HighScore), True, WHITE)
        HighScoreNumberRect = HighScoreNumber.get_rect(center = 
                                                      ((SCREEN_WIDTH + 90) 
                                                      // 2, 26))
        SCREEN.blit(OneUpText, OneUpTextRect)
        SCREEN.blit(OneUpScoreText, OneUpScoreRect)
        SCREEN.blit(HighScoreText, HighScoreTextRect)
        SCREEN.blit(HighScoreNumber, HighScoreNumberRect)
    
    def Update(self):
        # Update PacMan
        Main.PacManTeleport()       
        Main.ContinuePacManMovement()
        Main.PacManAnimation()
        # Update PinkGhost
        Main.PinkGhostTeleport()
        Main.ContinuePinkGhostMovement()
        Main.PinkGhostAnimation()
        Main.FrightenedMode()
        Main.KillPacMan()
        # Update Main
        Main.DrawBackground()
        Main.DrawPellets()
        Main.DrawEnergizers()
        Main.DrawPinkGhost()
        Main.DrawPacMan()
        Main.DrawLives()
        Main.GameOver()
        Main.EatPellets()
        Main.EatEnergizer()
        SCREEN.blit(MazeSurface, MazeRect)
        Main.ShowScore()
     
Main = Main()

BackgroundSurface = pygame.transform.scale(BackgroundSurface, 
                                          (Main.MazeWidth, 
                                           Main.MazeHeight))
BackgroundRect = BackgroundSurface.get_rect()

MazeSurface = pygame.Surface((Main.MazeWidth, Main.MazeHeight))
MazeRect = MazeSurface.get_rect(topleft = (Main.MazeOffsetX, 
                                           Main.MazeOffsetY))
Main.DrawMaze(MazeSurface)
#Main.PinkGhostStartPosition()

'''
Before the game starts ...
pregame = True
while pregame:
    if key button pressed:
        pregame = False
        run = True
'''

run = True
while run:
    SCREEN.fill(BLACK)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            Main.PacManMovement()
            
    Main.Update()
    pygame.display.update()
    CLOCK.tick(FPS)
    
pygame.quit()
0 Answers
Related