Edwin Navar
Edwin Navar

Reputation: 43

Mapping Grid Position To Matrix Position

I needed help, I was trying to map the position of a ghost in its current position such as (225, 175) to its position on the matrix (7,9), not sure what the math is to calculate its relative position, the reason why im asking is because it makes it easier to detect if theres a wall in matrix position as opposed to current position. I want to be able to do this so I can decide its next move at an intersection.

import pygame
import time
import random
import pickle
import math

pygame.init()
pygame.mixer.init()
pygame.display.set_caption("Pac-Man")

# Sets the size of the screen via (WIDTH, HEIGHT)
SCREEN_WIDTH = 478
SCREEN_HEIGHT = 608
# Speed of Characters
SPEED = 1
# Frames per second, how fast the game runs
FPS = 50
# Colors (RED,GREEN,BLUE)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0)
BLUE = (0, 0, 255)

# Sets the WIDTH and HEIGHT of the window
WINDOW = (SCREEN_WIDTH, SCREEN_HEIGHT)
# Displays the screen
SCREEN = pygame.display.set_mode(WINDOW)
CLOCK = pygame.time.Clock()

PacManStartSurface = pygame.transform.scale(pygame.image.load 
                                           ("PacManStart.png"), (23, 23))
PacManStartSurface.convert()
PacManStartRect = PacManStartSurface.get_rect(topleft = 
                                             (((SCREEN_WIDTH - 25) // 2),
                                             (SCREEN_HEIGHT + 144) // 2))

PacManSurface = pygame.transform.scale(pygame.image.load 
                                      ("PacManRight.png"), (23, 23))
PacManSurface.convert()
PacManRect = PacManStartSurface.get_rect(topleft = 
                                        (((SCREEN_WIDTH - 125) // 2),
                                        (SCREEN_HEIGHT + 144) // 2))

CurrentSurface = PacManStartSurface
CurrentRect = PacManStartRect 

BackgroundSurface = pygame.image.load("Background.png").convert()

PinkGhostSurface = pygame.transform.scale(pygame.image.load("PinkGhost.png")
                                           .convert(), (23, 23))
PinkGhostRect = PinkGhostSurface.get_rect()
YellowGhostSurface = pygame.transform.scale(pygame.image.load
                                           ("YellowGhost.png")
                                           .convert(), (23, 23))
YellowGhostRect = YellowGhostSurface.get_rect()
RedGhostSurface = pygame.transform.scale(pygame.image.load("RedGhost.png")
                                         .convert(), (23, 23))
RedGhostRect = RedGhostSurface.get_rect()
BlueGhostSurface = pygame.transform.scale(pygame.image.load("BlueGhost.png")
                                          .convert(), (23, 23))
BlueGhostRect = BlueGhostSurface.get_rect()

pygame.mixer.music.load('power_pellet.wav')

Font = pygame.font.Font("emulogic.ttf", 15)

class PacMan():
    def __init__(self):
        self.LIVES = 3
        
class Maze():
    def __init__(self):
        self.DOTS = []
        self.WALLS = []
        self.ENERGIZER = []
        self.GHOSTS = []
        self.WALLS_XY = []
        self.BLOCK_WIDTH = 25
        self.BLOCK_HEIGHT = 25
        self.MAZE_OFFSET_X = 0
        self.MAZE_OFFSET_Y = 50
        # 0 - Dots
        # 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], \
                      [0,0,0,0,0,2,2,1,4,4,4,1,2,2,0,0,0,0,0], \
                      [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.MAZE_X = self.BLOCK_WIDTH * (len(self.MATRIX[0]) 
                      + self.MAZE_OFFSET_X)
        self.MAZE_Y = self.BLOCK_HEIGHT * (len(self.MATRIX)
                      + self.MAZE_OFFSET_Y)
        self.MAZE_WIDTH = self.BLOCK_WIDTH * len(self.MATRIX[0])
        self.MAZE_HEIGHT = self.BLOCK_HEIGHT * 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 dot
                if self.MATRIX[ROW][COLUMN] == 0:
                    self.DOTS.append([(self.BLOCK_WIDTH * COLUMN),
                                      (self.BLOCK_HEIGHT * ROW), 4, 4])
                # Saves the position of each wall
                if self.MATRIX[ROW][COLUMN] == 1:
                    self.WALLS.append(pygame.draw.rect(MazeSurface, WHITE,
                                     [((self.BLOCK_WIDTH) * COLUMN),
                                      ((self.BLOCK_HEIGHT) * ROW), 
                                        self.BLOCK_WIDTH, self.BLOCK_HEIGHT]))
                # Saves the position of each Energizer
                if self.MATRIX[ROW][COLUMN] == 3:
                    self.ENERGIZER.append([(self.BLOCK_WIDTH * COLUMN),
                                           (self.BLOCK_HEIGHT * ROW), 14, 14])
                if self.MATRIX[ROW][COLUMN] == 4:
                    self.GHOSTS.append([(self.BLOCK_WIDTH * COLUMN), 
                                        (self.BLOCK_HEIGHT * ROW), 23, 23])
        for WALL in self.WALLS:
            X, Y, WIDTH, HEIGHT = WALL
            self.WALLS_XY.append((X, Y))
                    
class Main(Maze):
    def __init__(self):
        # Inherits Maze class
        Maze.__init__(self)
        self.TimeBetweenBites = 0.1
        self.LastBiteTime = time.time()
        self.MouthOpen = False
        self.PacManDirection = ""
        self.GhostDirection = ""
        self.SCORE = 0
        self.HIGH_SCORE = 0
        self.GridSizeX = SCREEN_HEIGHT // 19
        self.GridSizeY = SCREEN_HEIGHT // 32
        
    def PacManMovement(self):
        key = pygame.key.get_pressed()
        if key[pygame.K_LEFT] and not key[pygame.K_UP] \
                              and not key[pygame.K_DOWN]:
            self.PacManDirection = "LEFT"
        elif key[pygame.K_RIGHT] and not key[pygame.K_UP] \
                               and not key[pygame.K_DOWN]:
            self.PacManDirection = "RIGHT"
        elif key[pygame.K_UP] and not key[pygame.K_LEFT] \
                            and not key[pygame.K_RIGHT]:
            self.PacManDirection = "UP"
        elif key[pygame.K_DOWN] and not key[pygame.K_LEFT] \
                              and not key[pygame.K_RIGHT]:
            self.PacManDirection = "DOWN"
        
    def ContinuePacManMovement(self):
        if self.PacManDirection == "LEFT":
            CurrentRect.x -= SPEED
            self.PacManWallDetection(-1, 0, CurrentRect)
        if self.PacManDirection == "RIGHT":
            CurrentRect.x += SPEED
            self.PacManWallDetection(1, 0, CurrentRect)
        if self.PacManDirection == "UP":
            CurrentRect.y -= SPEED
            self.PacManWallDetection(0, -1, CurrentRect)
        if self.PacManDirection == "DOWN":
            CurrentRect.y += SPEED
            self.PacManWallDetection(0, 1, CurrentRect)
        
    def ContinueGhostMovement(self):
        if self.GhostDirection == "LEFT":
            PinkGhostRect.x -= SPEED
            self.GhostWallDetection(-1, 0, PinkGhostRect)
        if self.GhostDirection == "RIGHT":
            PinkGhostRect.x += SPEED
            self.GhostWallDetection(1, 0, PinkGhostRect)
        if self.GhostDirection == "UP":
            PinkGhostRect.y -= SPEED
            self.GhostWallDetection(0, -1, PinkGhostRect)
        if self.GhostDirection == "DOWN":
            PinkGhostRect.y += SPEED
            self.GhostWallDetection(-1, 0, PinkGhostRect)

    def PacManTeleport(self):
        if CurrentRect.right < 0:
            CurrentRect.right = SCREEN_WIDTH + 20
        if CurrentRect.left > SCREEN_WIDTH:
            CurrentRect.right = 0
    
    def GhostTeleport(self, Intersection):
        if PinkGhostRect.right < 0:
            PinkGhostRect.right = SCREEN_WIDTH + 20
            Intersection.append("LEFT")
        if PinkGhostRect.left > SCREEN_WIDTH:
            PinkGhostRect.right = 0
            Intersection.append("RIGHT")
            
    def PacManWallDetection(self, x, y, CurrentRect):
        CurrentRect.right += x
        for WALL in self.WALLS:
            COLLIDE = CurrentRect.colliderect(WALL)
            if COLLIDE:
                if x < 0: 
                    CurrentRect.left = WALL.right
                    CurrentSurface = pygame.transform.rotate(PacManSurface, 180)
                    MazeSurface.blit(CurrentSurface, CurrentRect)
                if x > 0:
                    CurrentRect.right = WALL.left
                break
        
        CurrentRect.top += y
        for WALL in self.WALLS:
            COLLIDE = CurrentRect.colliderect(WALL)
            if COLLIDE:
                if y < 0:
                    CurrentRect.top = WALL.bottom
                if y > 0:
                    CurrentRect.bottom = WALL.top
                break
            
    def GhostWallDetection(self, x, y, PinkGhostRect):
        PinkGhostRect.right += x
        for WALL in self.WALLS:
            COLLIDE = PinkGhostRect.colliderect(WALL)
            if COLLIDE:
                if x < 0:
                    PinkGhostRect.left = WALL.right
                    if random.randrange(0, 100) <= 40:
                        self.GhostDirection = "RIGHT"
                if x > 0:
                    PinkGhostRect.right = WALL.left
                    if random.randrange(0, 100) <= 40:
                        self.GhostDirection = "LEFT"
                break
        
        PinkGhostRect.top += y
        for WALL in self.WALLS:
            COLLIDE = PinkGhostRect.colliderect(WALL)
            if COLLIDE:
                if y < 0:
                    PinkGhostRect.top = WALL.bottom
                    if random.randrange(0, 100) <= 40:
                        self.GhostDirection = "DOWN"
                if y > 0:
                    PinkGhostRect.bottom = WALL.top 
                    if random.randrange(0, 100) <= 40:
                        self.GhostDirection = "UP"
                break
            
    def GetAvailableMoves(self):
        Intersection = []
        self.GhostTeleport(Intersection)
        print(PinkGhostRect.topleft)
        print(self.WALLS_XY)
        if ((PinkGhostRect.x - 1, PinkGhostRect.y)) not in self.WALLS_XY:
            Intersection.append("LEFT")
        if ((PinkGhostRect.x + 1, PinkGhostRect.y)) not in self.WALLS_XY:
            Intersection.append("RIGHT")
        if ((PinkGhostRect.x, PinkGhostRect.y - 1)) not in self.WALLS_XY:
            Intersection.append("UP")
        if ((PinkGhostRect.x, PinkGhostRect.y + 1)) not in self.WALLS_XY:
            Intersection.append("DOWN")
        print(Intersection)
        return Intersection
        
    def EatDots(self):
        for ROW in range(len(self.MATRIX)):
            for COLUMN in range(len(self.MATRIX[0])):
                for DOT in self.DOTS:
                    CHOMP = CurrentRect.colliderect(DOT)
                    if CHOMP:
                        Main.PlaySound(self, 0)
                        self.DOTS.remove(DOT)
                        self.MATRIX[ROW][COLUMN] = 3
                        self.SCORE += 10
        if self.SCORE > self.HIGH_SCORE:
            self.HIGH_SCORE = self.SCORE
        return str(self.SCORE), str(self.HIGH_SCORE)
    
    def EatEnergizer(self):
        for ROW in range(len(self.MATRIX)):
            for COLUMN in range(len(self.MATRIX[0])):
                for POWERUP in self.ENERGIZER:
                    CHOMP = CurrentRect.colliderect(POWERUP)
                    if CHOMP:
                        self.ENERGIZER.remove(POWERUP)
                        self.MATRIX[ROW][COLUMN] = 3
                        self.SCORE += 50
                        Main.PlaySound(self, 1)
        if self.SCORE > self.HIGH_SCORE:
            self.HIGH_SCORE = self.SCORE
        return str(self.SCORE), str(self.HIGH_SCORE)
    
    def EatGhosts(self):
        pass
                
    def DrawDots(self):
        for POSITION in self.DOTS:
            X = POSITION[0] + 13
            Y = POSITION[1] + 13
            WIDTH = POSITION[2]
            HEIGHT = POSITION[3]
            pygame.draw.circle(MazeSurface, YELLOW, (X, Y), 
                               WIDTH // 2, HEIGHT // 2)
            
    def DrawEnergizer(self):
        for POSITION in self.ENERGIZER:
            X = POSITION[0] + 13
            Y = POSITION[1] + 13
            WIDTH = POSITION[2] 
            HEIGHT = POSITION[3] 
            pygame.draw.circle(MazeSurface, YELLOW, (X, Y), 
                               WIDTH // 2, HEIGHT // 2)

    def DrawGhosts(self):        
        MazeSurface.blit(PinkGhostSurface, PinkGhostRect) 
        MazeSurface.blit(YellowGhostSurface, YellowGhostRect) 
        MazeSurface.blit(RedGhostSurface, RedGhostRect) 
        MazeSurface.blit(BlueGhostSurface, BlueGhostRect) 
        
    def GhostStartPosition(self):
        X, Y, WIDTH, HEIGHT = self.GHOSTS[0]
        PinkGhostRect.x = X
        PinkGhostRect.y = Y
        
        X, Y, WIDTH, HEIGHT = self.GHOSTS[1]
        YellowGhostRect.x = X
        YellowGhostRect.y = Y
        
        X, Y, WIDTH, HEIGHT = self.GHOSTS[2]
        RedGhostRect.x = X
        RedGhostRect.y = Y
        
        X, Y, WIDTH, HEIGHT = self.GHOSTS[3]
        BlueGhostRect.x = X
        BlueGhostRect.y = Y
        
    def PlaySound(self, Track):
        if Track == 0:
            Eat = pygame.mixer.Sound("pacman_chomp.wav")
            Eat.play()
            pygame.mixer.fadeout(400)
        if Track == 1:
            EatPellet = pygame.mixer.Sound("pacman_eatghost.wav")
            EatPellet.play()
            pygame.mixer.music.play(7)
            pygame.mixer.fadeout(400)
                
    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.HIGH_SCORE), 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 PacManBite(self):
        global CurrentSurface
        CurrentTime = time.time()
        if CurrentTime - self.LastBiteTime >= self.TimeBetweenBites:
            self.LastBiteTime = CurrentTime
            if self.MouthOpen:
                CurrentSurface = PacManStartSurface
            else:
                CurrentSurface = PacManSurface
            self.MouthOpen = not self.MouthOpen
            if self.PacManDirection == "LEFT":
                CurrentSurface = pygame.transform.rotate(CurrentSurface, 180)
            if self.PacManDirection == "RIGHT":
                CurrentSurface = CurrentSurface
            if self.PacManDirection == "UP":
                CurrentSurface = pygame.transform.rotate(CurrentSurface, 90)
            if self.PacManDirection == "DOWN":
                CurrentSurface = pygame.transform.rotate(CurrentSurface, 270)
    
    def PacManLives(self):
        pass
    
    def Update(self):
        Player.PacManTeleport()        
        Player.ContinuePacManMovement()
        Player.ContinueGhostMovement()
        Player.GetAvailableMoves()
        MazeSurface.blit(BackgroundSurface, BackgroundRect) 
        Player.DrawDots()
        Player.DrawEnergizer()
        Player.DrawGhosts()
        Player.EatDots()
        Player.EatEnergizer()
        MazeSurface.blit(CurrentSurface, CurrentRect)
        Player.PacManBite()
        SCREEN.blit(MazeSurface, MazeRect)
        Player.ShowScore()
        
Player = Main()

BackgroundSurface = pygame.transform.scale(BackgroundSurface, 
                                          (Player.MAZE_WIDTH, 
                                           Player.MAZE_HEIGHT))
BackgroundRect = BackgroundSurface.get_rect()

MazeSurface = pygame.Surface((Player.MAZE_WIDTH, Player.MAZE_HEIGHT))
MazeRect = MazeSurface.get_rect(topleft = (Player.MAZE_OFFSET_X, 
                                           Player.MAZE_OFFSET_Y))
Player.DrawMaze(MazeSurface)
Player.GhostStartPosition()

'''
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:
            Player.PacManMovement()
            
    Player.Update()
    pygame.display.update()
    CLOCK.tick(FPS)
    
pygame.quit()

Upvotes: 1

Views: 194

Answers (1)

Rabbid76
Rabbid76

Reputation: 210889

You just need to divide the position in the grid by the size of a tile with the // (floor-division) operator:

pos_in_maze = (225, 175)
column = pos_in_maze[0] // Player.BLOCK_WIDTH 
row    = pos_in_maze[1] // Player.BLOCK_HEIGHT

Since the size of a tile is 25 the results are 9 for the column and 7 for the row.

screen_pos = (225, 175)
column = (screen_pos[0] - Player.MAZE_OFFSET_X) // Player.BLOCK_WIDTH 
row    = (screen_pos[1] - Player.MAZE_OFFSET_Y) // Player.BLOCK_HEIGHT

Since MAZE_OFFSET_X is 0 and MAZE_OFFSET_Y is 50 the results are 9 for the column and 5 for the row.

Upvotes: 1

Related Questions