112 lines
4.2 KiB
Python
112 lines
4.2 KiB
Python
import math
|
|
import pygame
|
|
|
|
from data.classes_consts import CELL_SIZE, YELLOW, BLACK, RED
|
|
|
|
|
|
class Pacman:
|
|
def __init__(self, screen, x, y):
|
|
self.screen = screen
|
|
self.x = x
|
|
self.y = y
|
|
self.count = 0
|
|
|
|
def move(self, labyrinth, dx, dy):
|
|
new_x, new_y = self.x + dx, self.y + dy
|
|
if labyrinth[new_y][new_x] != "#":
|
|
self.x = new_x
|
|
self.y = new_y
|
|
|
|
def draw(self):
|
|
radius = CELL_SIZE // 2 - 4
|
|
start_angle = math.pi / 6
|
|
end_angle = -math.pi / 6
|
|
pygame.draw.circle(self.screen, YELLOW, (self.x * CELL_SIZE + CELL_SIZE // 2, self.y * CELL_SIZE + CELL_SIZE // 2), CELL_SIZE // 2 - 4)
|
|
# Calculate the points for the mouth
|
|
start_pos = (self.x* CELL_SIZE + CELL_SIZE // 2 + int(radius*1.3 * math.cos(start_angle)),
|
|
self.y* CELL_SIZE + CELL_SIZE // 2 - int(radius*1.3 * math.sin(start_angle)))
|
|
end_pos = (self.x* CELL_SIZE + CELL_SIZE // 2 + int(radius*1.3 * math.cos(end_angle)),
|
|
self.y* CELL_SIZE + CELL_SIZE // 2 - int(radius*1.3 * math.sin(end_angle)))
|
|
self.count += 1
|
|
if self.count%2==0:
|
|
# Draw the mouth by filling a polygon
|
|
pygame.draw.polygon(self.screen, BLACK, [(self.x* CELL_SIZE + CELL_SIZE // 2, self.y* CELL_SIZE + CELL_SIZE // 2), start_pos, end_pos])
|
|
|
|
|
|
class Ghost:
|
|
# Define the pixel art for the ghost using strings
|
|
ghost_pixels = [
|
|
" #### ",
|
|
"######",
|
|
"## # #",
|
|
"######",
|
|
"######",
|
|
"# # # "
|
|
]
|
|
|
|
def __init__(self, screen, x, y):
|
|
self.screen = screen
|
|
self.x = x
|
|
self.y = y
|
|
|
|
def move_towards_pacman(self, labyrinth, pacman):
|
|
if self.x < pacman.x and labyrinth[self.y][self.x + 1] != "#":
|
|
self.x += 1
|
|
elif self.x > pacman.x and labyrinth[self.y][self.x - 1] != "#":
|
|
self.x -= 1
|
|
elif self.y < pacman.y and labyrinth[self.y + 1][self.x] != "#":
|
|
self.y += 1
|
|
elif self.y > pacman.y and labyrinth[self.y - 1][self.x] != "#":
|
|
self.y -= 1
|
|
|
|
def draw(self):
|
|
pixel_size = CELL_SIZE // len(self.ghost_pixels) # Size of each pixel in the ghost art
|
|
for row_idx, row in enumerate(self.ghost_pixels):
|
|
for col_idx, pixel in enumerate(row):
|
|
if pixel == "#":
|
|
pixel_x = self.x * CELL_SIZE + col_idx * pixel_size
|
|
pixel_y = self.y * CELL_SIZE + row_idx * pixel_size
|
|
pygame.draw.rect(self.screen, RED, (pixel_x, pixel_y, pixel_size, pixel_size))
|
|
|
|
|
|
|
|
class StateIndexer:
|
|
"""Converts (x, y, cookie_dir) states to unique indices"""
|
|
def __init__(self):
|
|
# State space boundaries
|
|
self.x_min, self.x_max = -7, 7 # 15 values: -7 to 7 inclusive
|
|
self.y_min, self.y_max = -2, 2 # 5 values: -2 to 2 inclusive
|
|
self.dir_min, self.dir_max = 0, 3 # 4 directions: 0 to 3
|
|
|
|
# Ranges
|
|
self.x_range = self.x_max - self.x_min + 1 # 15
|
|
self.y_range = self.y_max - self.y_min + 1 # 5
|
|
self.dir_range = self.dir_max - self.dir_min + 1 # 4
|
|
|
|
# Multipliers for indexing
|
|
self.y_dir_product = self.y_range * self.dir_range # 5 * 4 = 20
|
|
self.total_states = self.x_range * self.y_dir_product # 15 * 20 = 300
|
|
|
|
def to_index(self, x, y, cookie_dir):
|
|
"""Convert state to unique index 0..299"""
|
|
# Convert to zero-based indices
|
|
x_idx = x - self.x_min # -7→0, -6→1, ..., 7→14
|
|
y_idx = y - self.y_min # -2→0, -1→1, ..., 2→4
|
|
dir_idx = cookie_dir - self.dir_min # 0→0, 1→1, 2→2, 3→3
|
|
|
|
# Linear mapping: (x * y_range * dir_range) + (y * dir_range) + dir
|
|
return (x_idx * self.y_dir_product) + (y_idx * self.dir_range) + dir_idx
|
|
|
|
def from_index(self, idx):
|
|
"""Convert index back to state"""
|
|
dir_idx = idx % self.dir_range
|
|
idx //= self.dir_range
|
|
y_idx = idx % self.y_range
|
|
x_idx = idx // self.y_range
|
|
|
|
return (
|
|
x_idx + self.x_min,
|
|
y_idx + self.y_min,
|
|
dir_idx + self.dir_min
|
|
)
|