aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md8
-rw-r--r--src/Game.py117
-rw-r--r--src/Player.py34
-rw-r--r--src/macpan.py1
-rw-r--r--src/map.py84
-rw-r--r--src/settings.py2
6 files changed, 155 insertions, 91 deletions
diff --git a/README.md b/README.md
index d137568..47d5c18 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,9 @@
# Description
+
- A very basic Pacman clone done in python using pygame library
# Run
+
- Open your favourite terminal
```bash
@@ -10,13 +12,15 @@ python3 macpan.py
```
# TODO
+
## Must DO
+
- [X] Setup the basic player movement mechanics
- [X] Replace the yellow circle with a pacman sprite
- [X] Setup the sprite animation for pacman
- [X] Setup collision with walls
- [X] Load the proper sprites for the map
-- [ ] Setup collision with the map
+- [X] Setup collision with the map
- [ ] Add the ghosts in the game
- [ ] Setup the sprite animation for the ghosts
- [ ] Develop an algorithm to make the ghosts find pacman in the map(BFS, A*)
@@ -26,6 +30,7 @@ python3 macpan.py
- [ ] Add the Algorithm for Clyde (Same as Blinky excepts when he gets 8 tiles close to pacman he retreats, So he is basically useless)
## Optional
+
- [ ] Setup a menu for the game
- [ ] Setup a simple score system
- [ ] Setup a proper sfx/audio for the game
@@ -33,4 +38,5 @@ python3 macpan.py
- [ ] Add firghtening mode for the ghosts
# EXTRA BONUS
+
- [ ] Make a nueral network agent that fully plays the game alone using reinforcment learning and PyTorch
diff --git a/src/Game.py b/src/Game.py
index 9d93786..58b8987 100644
--- a/src/Game.py
+++ b/src/Game.py
@@ -1,8 +1,11 @@
+from pygame.mouse import get_pressed
import Player
from Direction import DIRECTION
import settings as Settings
import map as Map
import pygame
+import math
+
class Game():
def __init__(self):
@@ -13,14 +16,16 @@ class Game():
pygame.init()
# Set the dimensions of the window
- screen = pygame.display.set_mode((Settings.settings.width, Settings.settings.height))
+ screen = pygame.display.set_mode(
+ (Settings.settings.width, Settings.settings.height))
# Sprite sheet for pacman
- sprite_sheet = pygame.image.load('../assets/pacman_left_sprite.png').convert_alpha();
+ sprite_sheet = pygame.image.load(
+ '../assets/pacman_left_sprite.png').convert_alpha()
player = Player.Player(sprite_sheet)
- # Set the circle's velocity
+ # Set the pacman velocity
dx = 0
dy = 0
@@ -29,32 +34,46 @@ class Game():
clock = pygame.time.Clock()
- sprite_width, sprite_height = 32, 32
+ maze = Map.Map()
+
+ # length of the map grid size
+ grid_x = Settings.settings.width // len(maze.maze[0])
+ grid_y = Settings.settings.height // len(maze.maze)
- map = Map.Map()
+ # Checks collision with walls
- grid_x = Settings.settings.width // len(map.maze[0])
- grid_y = (Settings.settings.height - 50) // len(map.maze)
+ # checks if the current position of pacman is either a dot, big dot or free
+ def is_valid(x, y):
+ is_dot = maze.maze[y][x] == Map.D
+ is_big_dot = maze.maze[y][x] == Map.BD
+ is_free = maze.maze[y][x] == 0
+ return (is_dot or is_free or is_big_dot)
- # Checks collision with walls
+ # checks collision with pacman and obstacles returns false if there is a collision and true otherwise
def check_collision(dx, dy):
- print(grid_x, grid_y)
- x = int((player.x + dx) / grid_x)
- y = int((player.y + dy) / grid_y)
- print(x, y)
- print(map.maze[x][y])
- is_dot = map.maze[x][y] == Map.D
- is_big_dot = map.maze[x][y] == Map.BD
- is_free = map.maze[x][y] == 0
- return not (is_dot or is_free or is_big_dot)
+ direct_x = [1, 0, -1, 0, 1, 1, -1, -1]
+ direct_y = [0, 1, 0, -1, -1, 1, -1, 1]
+
+ for i in range(len(direct_x)):
+ nx = (player.x + dx) + direct_x[i] * 14
+ ny = (player.y + dy) + direct_y[i] * 14
+ x = nx // grid_x
+ y = ny // grid_y
+ if not is_valid(x, y):
+ return False
+
+ return True
+
+
+
+
# Main game loop
running = True
-
while running:
# setting game fps
clock.tick(Settings.settings.fps)
@@ -65,6 +84,12 @@ class Game():
else:
counter = 0
+ screen.fill((0, 0, 0)) # Clear the screen
+
+ # Temporary values for delta_x and delta_y in the position of pacman
+ tx = dx
+ ty = dy
+
# Handling events
for event in pygame.event.get():
if event.type == pygame.QUIT:
@@ -73,35 +98,61 @@ class Game():
# Move the circle based on the pressed key
if event.key == pygame.K_w:
player.direction = DIRECTION.UP
- dy = -player.speed
- dx = 0 # Necssarry to move only horizontal or vertical
+ ty = -player.speed
+ tx = 0 # Necssarry to move only horizontal or vertical
elif event.key == pygame.K_s:
player.direction = DIRECTION.DOWN
- dy = player.speed
- dx = 0 # Necssarry to move only horizontal or vertical
+ ty = player.speed
+ tx = 0 # Necssarry to move only horizontal or vertical
elif event.key == pygame.K_a:
player.direction = DIRECTION.LEFT
- dx = -player.speed
- dy = 0 # Necssarry to move only horizontal or vertical
+ tx = -player.speed
+ ty = 0 # Necssarry to move only horizontal or vertical
elif event.key == pygame.K_d:
player.direction = DIRECTION.RIGHT
- dx = player.speed
- dy = 0 # Necssarry to move only horizontal or vertical
-
-
- # Update the circle's position and checking for collisions
- if not check_collision(dx, dy):
+ tx = player.speed
+ ty = 0 # Necssarry to move only horizontal or vertical
+
+ keys = pygame.key.get_pressed()
+ if keys[pygame.K_w]:
+ ty = -player.speed
+ tx = 0
+ elif keys[pygame.K_s]:
+ ty = player.speed
+ tx = 0
+ elif keys[pygame.K_a]:
+ tx = -player.speed
+ ty = 0
+ elif keys[pygame.K_d]:
+ tx = player.speed
+ ty = 0
+
+
+ # if tx and ty doesn't lead to colliding change the current dx and dy to them and other wise
+ # let pacman move in his previous direction
+ if check_collision(tx, ty):
+ dx = tx
+ dy = ty
+
+ if dx < 0:
+ player.direction = DIRECTION.LEFT
+ elif dx > 0:
+ player.direction = DIRECTION.RIGHT
+ elif dy < 0:
+ player.direction = DIRECTION.UP
+ elif dy > 0:
+ player.direction = DIRECTION.DOWN
+
+ if check_collision(dx, dy):
player.x += dx
player.y += dy
- screen.fill((0, 0, 0)) # Clear the screen
- map.draw_map(screen)
+ maze.draw_map(screen)
player.draw(screen, counter)
# Update the screen
pygame.display.flip()
-
# Quit Pygame
pygame.quit()
diff --git a/src/Player.py b/src/Player.py
index e0128d9..76dfe19 100644
--- a/src/Player.py
+++ b/src/Player.py
@@ -1,7 +1,6 @@
from typing import List
from Direction import DIRECTION
import pygame
-import settings as Settings
def get_sprites(sprite_sheet) -> List:
@@ -15,12 +14,15 @@ def get_sprites(sprite_sheet) -> List:
for col in range(columns):
x = col * sprite_width
y = row * sprite_height
-
- # Create a new surface for the current sprite and blit it from the sprite sheet onto this new surface
- new_sprite_surface = pygame.Surface((sprite_width, sprite_height), pygame.SRCALPHA)
- new_sprite_surface.blit(sprite_sheet, (0, 0), (x, y, x + sprite_width, y +sprite_height))
- # Add this new surface to our list of sprites
+ # Create a new surface for the current sprite and blit it from the
+ # sprite sheet onto this new surface
+ new_sprite_surface = pygame.Surface(
+ (sprite_width, sprite_height), pygame.SRCALPHA)
+ new_sprite_surface.blit(
+ sprite_sheet, (0, 0), (x, y, x + sprite_width, y + sprite_height))
+
+ # Add this new surface to our list of sprites
sprites.append(new_sprite_surface)
return sprites
@@ -28,20 +30,24 @@ def get_sprites(sprite_sheet) -> List:
class Player():
def __init__(self, sprite_sheet):
- self.x = 450
- self.y = 663
+ self.x = 75
+ self.y = 75
self.sprite = get_sprites(sprite_sheet)
- self.speed = 10
+ self.speed = 5
self.direction = DIRECTION.LEFT
def draw(self, screen, counter):
- pos = (self.x, self.y)
+ radius = 30 // 2
+ pos = (self.x - radius , self.y - radius)
+ # pygame.draw.circle(screen, 'green', pos, radius)
if self.direction == DIRECTION.UP:
- screen.blit(pygame.transform.rotate(self.sprite[counter // 5], 270), pos)
+ screen.blit(pygame.transform.rotate(
+ self.sprite[counter // 5], 270), pos)
elif self.direction == DIRECTION.DOWN:
- screen.blit(pygame.transform.rotate(self.sprite[counter // 5], 90), pos)
+ screen.blit(pygame.transform.rotate(
+ self.sprite[counter // 5], 90), pos)
elif self.direction == DIRECTION.RIGHT:
- screen.blit(pygame.transform.flip(self.sprite[counter // 5], True, False), pos)
+ screen.blit(pygame.transform.flip(
+ self.sprite[counter // 5], True, False), pos)
elif self.direction == DIRECTION.LEFT:
screen.blit(self.sprite[counter // 5], pos)
-
diff --git a/src/macpan.py b/src/macpan.py
index 93b81b3..a96a5fc 100644
--- a/src/macpan.py
+++ b/src/macpan.py
@@ -3,4 +3,3 @@ import Game
if __name__ == "__main__":
game = Game.Game()
game.init()
-
diff --git a/src/map.py b/src/map.py
index e05fc2f..9248241 100644
--- a/src/map.py
+++ b/src/map.py
@@ -3,7 +3,6 @@ import math
import settings as Settings
-
H = 1
V = 2
D = 4
@@ -20,7 +19,7 @@ PI = math.pi
class Map():
def __init__(self):
self.maze = [
- [TL, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, TR],
+ [TL, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H,H, H, H, H, H, H, H, H, H, H, H, H, H, TR],
[V, TL, H, H, H, H, H, H, H, H, H, H, H, H, TR, TL, H, H, H, H, H, H, H, H, H, H, H, H, TR, V],
[V, V, D, D, D, D, D, D, D, D, D, D, D, D, V, V, D, D, D, D, D, D, D, D, D, D, D, D, V, V],
[V, V, D, TL, H, H, TR, D, TL, H, H, H, TR, D, V, V, D, TL, H, H, H, TR, D, TL, H, H, TR, D, V, V],
@@ -53,55 +52,68 @@ class Map():
[V, V, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, V, V],
[V, BL, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, BR, V],
[BL, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, BR]
- ]
- self.dot_color = (255, 255, 255) # white
+ ]
+ self.dot_color = (255, 255, 255) # white
self.small_dot_radius = 4
self.big_dot_radius = 8
- self.line_color = (0, 0, 255) # Blue
+ self.line_color = (0, 0, 255) # Blue
self.line_vertical = Settings.settings.height // len(self.maze)
self.line_horizontal = Settings.settings.width // len(self.maze[0])
- self.line_stroke = 3
+ self.line_stroke = 1
def consturct_map(self):
pass
-
- def draw_wall(self, screen, flag , pos):
+ def draw_wall(self, screen, flag, pos):
if flag & V:
pos1 = (pos[0] + self.line_vertical * 0.5, pos[1])
pos2 = (pos1[0], pos1[1] + self.line_horizontal)
- pygame.draw.line(screen, self.line_color, pos1, pos2, self.line_stroke)
+ pygame.draw.line(screen, self.line_color,
+ pos1, pos2, self.line_stroke)
if flag & H:
pos1 = (pos[0], pos[1] + self.line_vertical * 0.5)
pos2 = (pos1[0] + self.line_horizontal, pos1[1])
- pygame.draw.line(screen, self.line_color, pos1, pos2, self.line_stroke)
+ pygame.draw.line(screen, self.line_color,
+ pos1, pos2, self.line_stroke)
if flag & D:
- pos1 = (pos[0] + self.line_vertical * 0.5, pos[1] + self.line_horizontal * 0.5)
- pygame.draw.circle(screen, self.dot_color, pos1, self.small_dot_radius)
+ pos1 = (pos[0] + self.line_vertical * 0.5,
+ pos[1] + self.line_horizontal * 0.5)
+ pygame.draw.circle(screen, self.dot_color,
+ pos1, self.small_dot_radius)
if flag & BD:
- pos1 = (pos[0] + self.line_vertical * 0.5, pos[1] + self.line_horizontal * 0.5)
- pygame.draw.circle(screen, self.dot_color, pos1, self.big_dot_radius)
+ pos1 = (pos[0] + self.line_vertical * 0.5,
+ pos[1] + self.line_horizontal * 0.5)
+ pygame.draw.circle(screen, self.dot_color,
+ pos1, self.big_dot_radius)
if flag & TR:
- pos1 = (pos[0] - self.line_vertical * 0.5, pos[1] + self.line_horizontal * 0.5)
- arc_rect = pygame.Rect(pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
- pygame.draw.arc(screen, self.line_color, arc_rect, 0, PI / 2, self.line_stroke)
+ pos1 = (pos[0] - self.line_vertical * 0.5,
+ pos[1] + self.line_horizontal * 0.5)
+ arc_rect = pygame.Rect(
+ pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
+ pygame.draw.arc(screen, self.line_color, arc_rect,
+ 0, PI / 2, self.line_stroke)
if flag & TL:
- pos1 = (pos[0] + self.line_vertical * 0.5, pos[1] + self.line_horizontal * 0.5)
- arc_rect = pygame.Rect(pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
- pygame.draw.arc(screen, self.line_color, arc_rect, PI / 2, PI, self.line_stroke)
+ pos1 = (pos[0] + self.line_vertical * 0.5,
+ pos[1] + self.line_horizontal * 0.5)
+ arc_rect = pygame.Rect(
+ pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
+ pygame.draw.arc(screen, self.line_color, arc_rect,
+ PI / 2, PI, self.line_stroke)
if flag & BL:
- pos1 = (pos[0] + self.line_vertical * 0.5, pos[1] - self.line_horizontal * 0.5)
- arc_rect = pygame.Rect(pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
- pygame.draw.arc(screen, self.line_color, arc_rect, PI, 3*PI / 2, self.line_stroke)
+ pos1 = (pos[0] + self.line_vertical * 0.5,
+ pos[1] - self.line_horizontal * 0.5)
+ arc_rect = pygame.Rect(
+ pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
+ pygame.draw.arc(screen, self.line_color, arc_rect,
+ PI, 3*PI / 2, self.line_stroke)
if flag & BR:
- pos1 = (pos[0] - self.line_vertical * 0.5, pos[1] - self.line_horizontal * 0.5)
- arc_rect = pygame.Rect(pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
- pygame.draw.arc(screen, self.line_color, arc_rect, 3*PI / 2, PI * 2, self.line_stroke)
-
-
+ pos1 = (pos[0] - self.line_vertical * 0.5,
+ pos[1] - self.line_horizontal * 0.5)
+ arc_rect = pygame.Rect(
+ pos1[0], pos1[1], self.line_vertical, self.line_horizontal)
+ pygame.draw.arc(screen, self.line_color, arc_rect,
+ 3*PI / 2, PI * 2, self.line_stroke)
-
-
def draw_map(self, screen):
rows = len(self.maze)
cols = len(self.maze[0])
@@ -109,14 +121,4 @@ class Map():
for j in range(cols):
pos = (j * self.line_horizontal, i * self.line_vertical)
self.draw_wall(screen, self.maze[i][j], pos)
-
-
-
-
-
-
-
-
-
-
-
+ # pygame.draw.rect(screen, 'red', (pos[0], pos[1], 32, 32), 2)
diff --git a/src/settings.py b/src/settings.py
index cdda2a4..9f0f118 100644
--- a/src/settings.py
+++ b/src/settings.py
@@ -1,7 +1,7 @@
class Settings():
def __init__(self):
self.width = 900
- self.height = 950
+ self.height = 990
self.fps = 60
settings = Settings()