Files
2024-10-29 17:18:30 +01:00

391 lines
13 KiB
Python

import sys
import pygame as pg
from pygame import mixer
from Blinky import Blinky
from Clyde import Clyde
from Inky import Inky
from Clyde import Clyde
from DrawType import DrawType
from Maze import Maze
from Pinky import Pinky
from Player import Player
from PointGrid import PointGrid
from Vec import Vec
import time
import os
# Variables
screen_width: int = 780
screen_height: int = 780
grid_cell_size: int = 26
startTime = time.time()
relativeStartTime = time.time()
delta_Time_Sec = 0
highscore = 0
clock = pg.time.Clock()
pointsToWin = 0
def auto_place_player(p: Player, m: Maze):
global default_pos_player
x = 15
for y in range(0, 29):
if m.is_free(Vec(x, y)):
p.position = Vec(x * grid_cell_size, y * grid_cell_size)
default_pos_player = Vec(x * grid_cell_size, y * grid_cell_size)
# Init Pygame
pg.init()
screen = pg.display.set_mode((screen_width, screen_height), pg.RESIZABLE + pg.SCALED, vsync=1)
overlayFont = pg.font.SysFont("Comic Sans", 22)
finishFont = pg.font.SysFont("Comic Sans", 70)
restartFont = pg.font.SysFont("Comic Sans", 22)
pg.display.set_icon(pg.image.load("/PacMan.png"))
pg.display.set_caption("PacMan")
pause = False
mixer.init()
mixer.music.load("/pacman-background-music.wav")
mixer.music.queue("/pacman-background-music.wav", loops=100)
mixer.music.set_volume(0.05)
mixer.music.play()
click_sound = pg.mixer.Sound("/click.wav")
click_sound.set_volume(0.05)
# Init Player
default_pos_player: Vec = None
player = Player(Vec(0, 0), Vec(grid_cell_size / 2 - 1, grid_cell_size / 2 - 1), 2, grid_cell_size)
player.velocity = Vec(0, 0)
# Generate Maze
maze = Maze(grid_cell_size)
maze.read_file("../Game/maze.pac")
auto_place_player(player, maze)
# Init Points
points = PointGrid(grid_cell_size, screen_width, screen_height, maze, 3)
# Ghosts
last_time_ghosts_afraid = 0
# Blinky
blinky = Blinky(Vec(12 * grid_cell_size, 15 * grid_cell_size), Vec(grid_cell_size / 2 - 1, grid_cell_size / 2 - 1),
screen_width, grid_cell_size, player, maze.maze)
blinky_start_delay = 2
# Pinky
pinky = Pinky(Vec(13 * grid_cell_size, 15 * grid_cell_size), Vec(grid_cell_size / 2 - 1, grid_cell_size / 2 - 1),
screen_width, grid_cell_size, player, maze.maze)
pinky_start_delay = 5.5
# Inky
inky = Inky(Vec(14 * grid_cell_size, 15 * grid_cell_size), Vec(grid_cell_size / 2 - 1, grid_cell_size / 2 - 1),
screen_width, grid_cell_size, player, maze.maze, blinky.position, screen)
inky_start_delay = 9
# Clyde
clyde = Clyde(Vec(15 * grid_cell_size, 15 * grid_cell_size), Vec(grid_cell_size / 2 - 1, grid_cell_size / 2 - 1),
screen_width, grid_cell_size, player, maze.maze)
clyde_start_delay = 12.5
# Images
player_image = pg.image.load("/PacMan.png")
player_image = pg.transform.scale(player_image, (grid_cell_size, grid_cell_size))
player_image2 = pg.image.load("/PacMan2.png")
player_image2 = pg.transform.scale(player_image2, (grid_cell_size, grid_cell_size))
ghost_afraid_image = pg.image.load("/GhostAfraid.png")
ghost_afraid_image = pg.transform.scale(ghost_afraid_image, (grid_cell_size, grid_cell_size))
blinky_image = pg.image.load("/Blinky.png")
blinky_image = pg.transform.scale(blinky_image, (grid_cell_size, grid_cell_size))
pinky_image = pg.image.load("/Pinky.png")
pinky_image = pg.transform.scale(pinky_image, (grid_cell_size, grid_cell_size))
inky_image = pg.image.load("/Inky.png")
inky_image = pg.transform.scale(inky_image, (grid_cell_size, grid_cell_size))
clyde_image = pg.image.load("/Clyde.png")
clyde_image = pg.transform.scale(clyde_image, (grid_cell_size, grid_cell_size))
# Function called when game should close
def on_game_exit():
pg.quit()
os.system("python3 ../Start/Start.py")
# function to clear the screen
def clear_screen():
screen.fill((255, 255, 255))
def check_points_possible_to_eat():
global last_time_ghosts_afraid
global pause
global finishFont
check = Vec(player.position.x + grid_cell_size / 2, player.position.y + grid_cell_size / 2)
surrounding_point = points.get_surrounding_points(check)
for point in surrounding_point:
if check.distance(point.position) < 3:
if not point.eaten:
pg.mixer.Sound.play(click_sound)
if point.big:
player.score += 50
last_time_ghosts_afraid = time.time()
else:
player.score += 10
point.eat()
# Highscore Overlay
def draw_highscore():
if os.path.getsize("/highscore.pac") == 0:
text = "Schnellste gewonnene Runde: Keine vorhanden :P"
else:
with open("/highscore.pac", "r") as myTest:
content = myTest.read()
sec = int(content) % 60
min = int(content) / 60
text = "Schnellste gewonnene Runde: " + str(int(min)) + " Minuten " + str(sec) + " Sekunden"
highscore_screen = restartFont.render(text, True, (0, 0, 0))
highscore_rect = highscore_screen.get_rect()
highscore_rect.center = (screen_width // 2, screen_height // 2 + 80)
screen.blit(highscore_screen, highscore_rect)
# Aktueller Score Overlay
def draw_currentscore():
global delta_Time_Sec
sec = delta_Time_Sec % 60
min = int(delta_Time_Sec / 60)
currentscore_screen = restartFont.render("Aktuelle Runde: " + str(min) + " Minuten " + str(sec) + " Sekunden", True,
(0, 0, 0))
currentscore_rect = currentscore_screen.get_rect()
currentscore_rect.center = (screen_width // 2, screen_height // 2 + 110)
screen.blit(currentscore_screen, currentscore_rect)
# Punkte Overlay
def draw_overlayPoints():
global overlayFont
pointSurface = overlayFont.render("Punkte: " + str(player.score), True, (0, 0, 0))
textrect = pointSurface.get_rect()
textrect.center = (screen_width // 2, screen_height - 30)
screen.blit(pointSurface, textrect)
hp_surface = overlayFont.render("Übrige Leben: " + str(player.hp - 1), True, (0, 0, 0))
hp_rect = hp_surface.get_rect()
hp_rect.center = (screen_width, screen_height - 30)
hp_rect.right = (screen_width - 10)
screen.blit(hp_surface, hp_rect)
# Timer Overlay
def draw_overlayTime():
global overlayFont
global delta_Time_Sec
global delta_Time_Minute
delta_Time_Sec = int(time.time() - startTime)
rest = delta_Time_Sec % 60
delta_Time_Minute = delta_Time_Sec - rest
timeSurface = overlayFont.render(str(delta_Time_Minute // 60) + " min " + str(rest) + " sek", True, (0, 0, 0))
timerect = timeSurface.get_rect()
timerect.center = (0, screen_height - 30)
timerect.left = 10
screen.blit(timeSurface, timerect)
def reset_positions():
player.position = default_pos_player.get_instance()
blinky.set_position(blinky.default_pos.get_instance())
pinky.set_position(pinky.default_pos.get_instance())
inky.set_position(inky.default_pos.get_instance())
clyde.set_position(clyde.default_pos.get_instance())
def restart():
global pause
global startTime
global relativeStartTime
global last_time_ghosts_afraid
player.hp = 3
player.score = 0
startTime = time.time()
relativeStartTime = time.time()
reset_positions()
blinky.stateChange = time.time()
pinky.stateChange = time.time()
inky.stateChange = time.time()
clyde.stateChange = time.time()
last_time_ghosts_afraid = 0
blinky.chase = True
pinky.chase = True
inky.chase = True
clyde.chase = True
for x in range(0, 30):
for y in range(0, 30):
points.points[x][y].eaten = maze.maze[x][y] != 0
pause = False
def save_highscore():
global highscore
global delta_Time_Sec
if os.path.getsize("/highscore.pac") == 0:
with open("/highscore.pac", "w") as overwrite:
overwrite.write(str(delta_Time_Sec))
highscore = delta_Time_Sec
else:
with open("/highscore.pac", "r") as getScore:
if delta_Time_Sec < int(getScore.read()):
with open("/highscore.pac", "w") as overwrite:
overwrite.write(str(delta_Time_Sec))
highscore = delta_Time_Sec
def check_ghost_collisions():
global relativeStartTime
global pause
global finishFont
global restartFont
global last_time_ghosts_afraid
if (blinky.position.distance(player.position) < 20 or pinky.position.distance(
player.position) < 20 or inky.position.distance(player.position) < 20 or clyde.position.distance(
player.position) < 20) \
and time.time() - player.last_time_hit > 1 and time.time() - last_time_ghosts_afraid > 8:
relativeStartTime = time.time()
player.last_time_hit = time.time()
player.hp -= 1
reset_positions()
def calc_points_to_win():
global maze
count = 0
for i in maze.maze:
for j in i:
if j == 0:
count += 1
count -= 4
count *= 10
count += 4 * 50
return count
pointsToWin = calc_points_to_win()
while True:
for e in pg.event.get():
if e.type == pg.QUIT:
on_game_exit()
break
# Clear the screen
clear_screen()
maze.draw(screen, (200, 200, 200), (150, 150, 150))
# Draw the points
points.draw(screen, (255, 100, 0), DrawType.circle)
if not pause:
# Player actions
player.poll_keys(maze)
player.move(maze)
player.check_bounds_move(screen_width, screen_height)
player.draw(screen, (252, 186, 3), DrawType.image, grid_cell_size,
image=pg.transform.rotate(player_image if player.get_state() else player_image2,
player.get_rotation()))
check_points_possible_to_eat()
draw_overlayPoints()
draw_overlayTime()
# Check Ghosts
if time.time() - last_time_ghosts_afraid < 8:
if time.time() - relativeStartTime > pinky_start_delay:
pinky.idle()
if time.time() - relativeStartTime > blinky_start_delay:
blinky.idle()
if time.time() - relativeStartTime > inky_start_delay:
inky.idle()
if time.time() - relativeStartTime > clyde_start_delay:
clyde.idle()
blinky.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(ghost_afraid_image, blinky.is_mirrored(), False))
pinky.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(ghost_afraid_image, pinky.is_mirrored(), False))
inky.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(ghost_afraid_image, inky.is_mirrored(), False))
clyde.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(ghost_afraid_image, clyde.is_mirrored(), False))
else:
if time.time() - relativeStartTime > blinky_start_delay:
blinky.run()
if time.time() - relativeStartTime > pinky_start_delay:
pinky.run()
if time.time() - relativeStartTime > inky_start_delay:
inky.run()
if time.time() - relativeStartTime > clyde_start_delay:
clyde.run()
blinky.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(blinky_image, blinky.is_mirrored(), False))
pinky.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(pinky_image, pinky.is_mirrored(), False))
inky.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(inky_image, inky.is_mirrored(), False))
clyde.draw(screen, (0, 0, 0), DrawType.image, grid_cell_size,
image=pg.transform.flip(clyde_image, clyde.is_mirrored(), False))
check_ghost_collisions()
if player.score >= pointsToWin:
save_highscore()
win_screen = finishFont.render("Gewonnen!", True, (0, 0, 0))
win_rect = win_screen.get_rect()
win_rect.center = (screen_width // 2, screen_height // 2)
screen.blit(win_screen, win_rect)
restart_screen = restartFont.render("Drücke 'R' um noch eine Runde zu spielen!", True, (0, 0, 0))
restart_rect = restart_screen.get_rect()
restart_rect.center = (screen_width // 2, screen_height // 2 + 50)
screen.blit(restart_screen, restart_rect)
draw_highscore()
draw_currentscore()
keys = pg.key.get_pressed()
pause = True
if keys[pg.K_r]:
restart()
elif player.hp == 0:
lose_screen = finishFont.render("Game Over!", True, (0, 0, 0))
lose_rect = lose_screen.get_rect()
lose_rect.center = (screen_width // 2, screen_height // 2)
screen.blit(lose_screen, lose_rect)
restart_screen = restartFont.render("Drücke 'R' um es wieder zu versuchen!", True, (0, 0, 0))
restart_rect = restart_screen.get_rect()
restart_rect.center = (screen_width // 2, screen_height // 2 + 50)
screen.blit(restart_screen, restart_rect)
draw_highscore()
keys = pg.key.get_pressed()
pause = True
if keys[pg.K_r]:
restart()
# Update the display
pg.display.flip()
clock.tick(60)