Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
339 changes: 102 additions & 237 deletions games/Snake-Game/Snake-Game.py

Large diffs are not rendered by default.

25 changes: 12 additions & 13 deletions games/Snake-Game/food.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,21 @@ def __init__(self):

def reposition(self, snake: Snake):
attempts = 0

# Get all snake positions (aligned to grid)
snake_positions = [(int(p.xcor()), int(p.ycor())) for p in snake.parts]
snake_positions.append((int(snake.head.xcor()), int(snake.head.ycor())))

while attempts < 100:
x = random.randint(-14, 14) * 20
y = random.randint(-14, 14) * 20
overlaps = False

if snake.head.distance(x, y) < COLLISION_DISTANCE:
overlaps = True
for p in snake.parts:
if p.distance(x, y) < COLLISION_DISTANCE:
overlaps = True
break

if not overlaps:

# Check exact match instead of distance
if (x, y) not in snake_positions:
self.item.goto(x, y)
break
return

attempts += 1

if attempts >= 100:
self.item.goto(2000, 2000)
# fallback (rare case)
self.item.goto(2000, 2000)
68 changes: 65 additions & 3 deletions games/Snake-Game/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import pygame
import turtle
import time
from constants import SCREEN_WIDTH, SCREEN_HEIGHT, COLLISION_DISTANCE, SLEEP_TIME
from snake import Snake
from food import Food
from scoreboard import Scoreboard


class SnakeGame:
def __init__(self):
# Game state
self.paused = False
self.delay = SLEEP_TIME
self.level = 1

# Screen setup
self.screen = turtle.Screen()
self.screen.title("Snake Game (Modular OOP)")
self.screen.bgcolor("black")
Expand All @@ -15,16 +23,23 @@ def __init__(self):

self._draw_borders()

# Game objects
self.snake = Snake()
self.food = Food()
self.scoreboard = Scoreboard()

# Sound setup
pygame.mixer.init()
self.eat_sound = pygame.mixer.Sound("sounds/Apple_Eating.mp3")
self.gameover_sound = pygame.mixer.Sound("sounds/Game_over.mp3")

# Keyboard bindings
self.screen.listen()
self.screen.onkeypress(self.snake.move_up, "Up")
self.screen.onkeypress(self.snake.move_down, "Down")
self.screen.onkeypress(self.snake.move_left, "Left")
self.screen.onkeypress(self.snake.move_right, "Right")
self.screen.onkeypress(self.toggle_pause, "p") # Pause key

def _draw_borders(self):
box = turtle.Turtle()
Expand All @@ -38,28 +53,75 @@ def _draw_borders(self):
box.forward(600)
box.right(90)

# Countdown before game starts
def countdown(self):
for text in ["3", "2", "1", "GO!"]:
self.scoreboard.show_message(text)
self.screen.update()
time.sleep(1)

self.scoreboard.update_display()

# Pause toggle
def toggle_pause(self):
self.paused = not self.paused

if self.paused:
self.scoreboard.show_message("PAUSED")
else:
self.scoreboard.update_display()

def run(self):
self.countdown() # Start countdown

while True:
self.screen.update()

# Pause check
if self.paused:
continue

# Boundary collision
if self.snake.check_boundary_collision():
self.gameover_sound.play()
self.snake.reset()
self.scoreboard.reset()
self.delay = SLEEP_TIME
self.level = 1

# Check food collision
# Food collision
if self.snake.head.distance(self.food.item) < COLLISION_DISTANCE:
self.food.reposition(self.snake)
self.snake.add_part()

self.scoreboard.increase()
self.eat_sound.play()

# Level system
if self.scoreboard.score % 5 == 0:
self.level += 1
self.delay -= 0.01

# Optional level message
self.scoreboard.show_message(f"LEVEL {self.level}")
self.screen.update()
time.sleep(0.5)
self.scoreboard.update_display()

# Move snake
self.snake.move()

# Check body collision
# Self collision
if self.snake.check_self_collision():
self.gameover_sound.play()
self.snake.reset()
self.scoreboard.reset()
self.delay = SLEEP_TIME
self.level = 1

# Game speed
time.sleep(self.delay)

time.sleep(SLEEP_TIME)

if __name__ == "__main__":
game = SnakeGame()
Expand Down
24 changes: 21 additions & 3 deletions games/Snake-Game/scoreboard.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,45 @@
import turtle

class Scoreboard:
def __init__(self):
self.score = 0
self.level = 1
self.high_score = 0

self.display = turtle.Turtle()
self.display.hideturtle()
self.display.color("white")
self.display.penup()
self.display.goto(0, 320)

self.update_display()

def update_display(self):
self.display.clear()
self.display.write(
f"Score: {self.score}",
align="center",
f"Score: {self.score} | Level: {self.level} | High Score: {self.high_score}",
align="center",
font=("Arial", 18, "normal")
)

def increase(self):
self.score += 1

# Update high score
if self.score > self.high_score:
self.high_score = self.score

self.update_display()

def level_up(self):
self.level += 1
self.update_display()

def reset(self):
self.score = 0
self.level = 1
self.update_display()

def show_message(self, text):
self.display.goto(0, 0)
self.display.write(text, align="center", font=("Arial", 30, "bold"))
self.display.goto(0, 320)
39 changes: 27 additions & 12 deletions games/Snake-Game/snake.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,32 @@ def move(self):
y = self.parts[i - 1].ycor()
self.parts[i].goto(x, y)

if len(self.parts) > 0:
if self.parts:
self.parts[0].goto(self.head.xcor(), self.head.ycor())

if self.head.direction == "up":
self.head.sety(self.head.ycor() + MOVE_DISTANCE)
if self.head.direction == "down":
self.head.sety(self.head.ycor() - MOVE_DISTANCE)
if self.head.direction == "left":
self.head.setx(self.head.xcor() - MOVE_DISTANCE)
if self.head.direction == "right":
self.head.setx(self.head.xcor() + MOVE_DISTANCE)
moves = {
"up": (0, MOVE_DISTANCE),
"down": (0, -MOVE_DISTANCE),
"left": (-MOVE_DISTANCE, 0),
"right": (MOVE_DISTANCE, 0)
}

if self.head.direction in moves:
dx, dy = moves[self.head.direction]
self.head.goto(self.head.xcor() + dx, self.head.ycor() + dy)

def add_part(self):
new_part = turtle.Turtle()
new_part.shape("square")
new_part.color("lightgreen")
new_part.penup()

if self.parts:
last_part = self.parts[-1]
new_part.goto(last_part.xcor(), last_part.ycor())
else:
new_part.goto(self.head.xcor(), self.head.ycor())

self.parts.append(new_part)

def check_boundary_collision(self) -> bool:
Expand All @@ -61,15 +70,21 @@ def check_boundary_collision(self) -> bool:
)

def check_self_collision(self) -> bool:
for p in self.parts:
if p.distance(self.head) < BODY_COLLISION_DISTANCE:
head_pos = (int(self.head.xcor()), int(self.head.ycor()))

for p in self.parts[1:]: # It will skip first segment
if (int(p.xcor()), int(p.ycor())) == head_pos:
return True
return False

def reset(self):
time.sleep(1)
self.head.goto(0, 0)
self.head.direction = "stop"

for p in self.parts:
p.goto(1000, 1000)

self.parts.clear()

def is_moving(self):
return self.head.direction != "stop"
Binary file added games/Snake-Game/sounds/Apple_Eating.mp3
Binary file not shown.
Binary file added games/Snake-Game/sounds/Game_over.mp3
Binary file not shown.
1 change: 1 addition & 0 deletions games/Snake-Game/sounds/ex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Sound Files are here in this directory.
Loading