Skip to content

Commit baf3b9e

Browse files
committed
Feat: Add spacebar pause, resume, and countdown flow to Snake
1 parent d181b12 commit baf3b9e

2 files changed

Lines changed: 127 additions & 99 deletions

File tree

games/Snake-Game/Snake-Game.py

Lines changed: 80 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
11
import turtle
22
import random
33
import time
4-
# ================= SOUND =================
4+
5+
# ================= SOUND SYSTEM =================
6+
pygame_installed = False
7+
eat_sound = None
8+
gameover_sound = None
9+
510
try:
611
import pygame
712
pygame.mixer.init()
8-
eat_sound = pygame.mixer.Sound("sounds/eat.wav")
9-
gameover_sound = pygame.mixer.Sound("sounds/gameover.wav")
10-
pygame_installed = True
13+
14+
# Try loading default wav files
15+
try:
16+
eat_sound = pygame.mixer.Sound("sounds/eat.wav")
17+
gameover_sound = pygame.mixer.Sound("sounds/gameover.wav")
18+
pygame_installed = True
19+
except Exception:
20+
# Fallback to alternate mp3 file naming schemes
21+
try:
22+
eat_sound = pygame.mixer.Sound("sounds/Apple_Eating.mp3")
23+
gameover_sound = pygame.mixer.Sound("sounds/Game_over.mp3")
24+
pygame_installed = True
25+
except Exception:
26+
print("⚠️ Warning: Sound files not found in 'sounds/' folder. Game will run silently.")
27+
pygame_installed = False
1128
except ImportError:
12-
pygame_installed = False
1329
print("⚠️ Warning: pygame module not found. Game will run without sound effects.")
1430

1531

@@ -109,12 +125,13 @@ def generate_food():
109125

110126
generate_food()
111127

112-
# ================= SCORE =================
128+
# ================= STATE VARIABLES =================
113129

114130
score = 0
115131
high_score = 0
116132
level = 1
117133
speed = 0.05
134+
game_state = "IDLE"
118135

119136
score_text = turtle.Turtle()
120137
score_text.hideturtle()
@@ -132,23 +149,7 @@ def update_score():
132149

133150
update_score()
134151

135-
# ================= PAUSE =================
136-
137-
paused = False
138-
139-
def toggle_pause():
140-
global paused
141-
paused = not paused
142-
143-
game_text.clear()
144-
145-
if paused:
146-
game_text.write("PAUSED", align="center", font=("Arial", 24, "bold"))
147-
148-
screen.listen()
149-
screen.onkeypress(toggle_pause, "p")
150-
151-
# ================= COUNTDOWN =================
152+
# ================= CONTROL INFRASTRUCTURE =================
152153

153154
def countdown():
154155
for text in ["3", "2", "1", "GO!"]:
@@ -158,32 +159,62 @@ def countdown():
158159
time.sleep(1)
159160
game_text.clear()
160161

161-
countdown()
162+
def handle_spacebar():
163+
global game_state, score, level, speed
164+
165+
if game_state == "IDLE":
166+
countdown()
167+
game_state = "PLAYING"
168+
169+
elif game_state == "PLAYING":
170+
game_state = "PAUSED"
171+
game_text.clear()
172+
game_text.write("PAUSED", align="center", font=("Arial", 24, "bold"))
173+
174+
elif game_state == "PAUSED":
175+
game_state = "PLAYING"
176+
game_text.clear()
177+
178+
elif game_state == "GAME_OVER":
179+
head.goto(0, 0)
180+
head.direction = "stop"
181+
for p in parts:
182+
p.goto(1000, 1000)
183+
parts.clear()
184+
185+
score = 0
186+
level = 1
187+
speed = 0.05
188+
189+
update_score()
190+
countdown()
191+
game_state = "PLAYING"
162192

163-
# ================= CONTROLS =================
193+
screen.listen()
194+
screen.onkeypress(handle_spacebar, "space")
164195

165196
def move_up():
166-
if head.direction != "down":
197+
if head.direction != "down" and game_state == "PLAYING":
167198
head.direction = "up"
168199

169200
def move_down():
170-
if head.direction != "up":
201+
if head.direction != "up" and game_state == "PLAYING":
171202
head.direction = "down"
172203

173204
def move_left():
174-
if head.direction != "right":
205+
if head.direction != "right" and game_state == "PLAYING":
175206
head.direction = "left"
176207

177208
def move_right():
178-
if head.direction != "left":
209+
if head.direction != "left" and game_state == "PLAYING":
179210
head.direction = "right"
180211

181212
screen.onkeypress(move_up, "Up")
182213
screen.onkeypress(move_down, "Down")
183214
screen.onkeypress(move_left, "Left")
184215
screen.onkeypress(move_right, "Right")
185216

186-
# ================= MOVE =================
217+
# ================= MOVE PHYSICS =================
187218

188219
def move():
189220
if head.direction == "up":
@@ -195,36 +226,15 @@ def move():
195226
elif head.direction == "right":
196227
head.setx(head.xcor() + GRID_SIZE)
197228

198-
# ================= RESET =================
199-
200-
def reset_game():
201-
global score, level, speed
202-
203-
if pygame_installed:
204-
gameover_sound.play()
205-
206-
time.sleep(1)
207-
208-
head.goto(0, 0)
209-
head.direction = "stop"
210-
211-
for p in parts:
212-
p.goto(1000, 1000)
213-
parts.clear()
214-
215-
score = 0
216-
level = 1
217-
speed = 0.05
218-
219-
update_score()
220-
221229
# ================= MAIN LOOP =================
222230

223-
while True:
231+
game_text.write("Press SPACEBAR to Start", align="center", font=("Arial", 24, "bold"))
224232

233+
while True:
225234
screen.update()
226235

227-
if paused:
236+
if game_state in ["IDLE", "PAUSED", "GAME_OVER"]:
237+
time.sleep(0.1)
228238
continue
229239

230240
# Border collision
@@ -234,24 +244,25 @@ def reset_game():
234244
head.ycor() > BORDER_LIMIT or
235245
head.ycor() < -BORDER_LIMIT
236246
):
237-
reset_game()
247+
if pygame_installed and gameover_sound:
248+
gameover_sound.play()
249+
game_text.write("GAME OVER - Press SPACE to Restart", align="center", font=("Arial", 20, "bold"))
250+
game_state = "GAME_OVER"
251+
continue
238252

239253
# Food collision
240254
if head.distance(food) < GRID_SIZE:
241-
242-
if pygame_installed:
255+
if pygame_installed and eat_sound:
243256
eat_sound.play()
244257

245258
score += current_food["points"]
246259

247260
if score > high_score:
248261
high_score = score
249262

250-
# LEVEL SYSTEM
251263
if score % 5 == 0:
252264
level += 1
253265
speed -= 0.005
254-
255266
game_text.clear()
256267
game_text.write(f"LEVEL {level}", align="center", font=("Arial", 24, "bold"))
257268
screen.update()
@@ -264,9 +275,7 @@ def reset_game():
264275
new_part.shape("circle")
265276
new_part.color("#66FF99")
266277
new_part.penup()
267-
268278
parts.append(new_part)
269-
270279
update_score()
271280

272281
# Move body
@@ -283,6 +292,13 @@ def reset_game():
283292
# Self collision
284293
for p in parts:
285294
if p.distance(head) < 12:
286-
reset_game()
295+
if pygame_installed and gameover_sound:
296+
gameover_sound.play()
297+
game_text.write("GAME OVER - Press SPACE to Restart", align="center", font=("Arial", 20, "bold"))
298+
game_state = "GAME_OVER"
299+
break
300+
301+
if game_state == "GAME_OVER":
302+
continue
287303

288-
time.sleep(speed)
304+
time.sleep(speed)

games/Snake-Game/main.py

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414

1515
class SnakeGame:
1616
def __init__(self):
17-
# Game state
18-
self.paused = False
17+
self.game_state = "IDLE"
1918
self.delay = SLEEP_TIME
2019
self.level = 1
2120

@@ -33,6 +32,13 @@ def __init__(self):
3332
self.food = Food()
3433
self.scoreboard = Scoreboard()
3534

35+
# Dedicated message text engine (matches the working Snake-game.py pattern)
36+
self.game_text = turtle.Turtle()
37+
self.game_text.hideturtle()
38+
self.game_text.color("white")
39+
self.game_text.penup()
40+
self.game_text.goto(0, 0)
41+
3642
# Sound setup
3743
self.pygame_installed = pygame_installed
3844
if self.pygame_installed:
@@ -50,7 +56,7 @@ def __init__(self):
5056
self.screen.onkeypress(self.snake.move_down, "Down")
5157
self.screen.onkeypress(self.snake.move_left, "Left")
5258
self.screen.onkeypress(self.snake.move_right, "Right")
53-
self.screen.onkeypress(self.toggle_pause, "p") # Pause key
59+
self.screen.onkeypress(self.handle_spacebar, "space")
5460

5561
def _draw_borders(self):
5662
box = turtle.Turtle()
@@ -64,62 +70,70 @@ def _draw_borders(self):
6470
box.forward(600)
6571
box.right(90)
6672

67-
# Countdown before game starts
6873
def countdown(self):
6974
for text in ["3", "2", "1", "GO!"]:
70-
self.scoreboard.show_message(text)
75+
self.game_text.clear()
76+
self.game_text.write(text, align="center", font=("Arial", 30, "bold"))
7177
self.screen.update()
7278
time.sleep(1)
73-
74-
self.scoreboard.update_display()
75-
76-
# Pause toggle
77-
def toggle_pause(self):
78-
self.paused = not self.paused
79-
80-
if self.paused:
81-
self.scoreboard.show_message("PAUSED")
82-
else:
83-
self.scoreboard.update_display()
79+
self.game_text.clear()
80+
81+
def handle_spacebar(self):
82+
if self.game_state == "IDLE":
83+
self.countdown()
84+
self.game_state = "PLAYING"
85+
86+
elif self.game_state == "PLAYING":
87+
self.game_state = "PAUSED"
88+
self.game_text.clear()
89+
self.game_text.write("PAUSED", align="center", font=("Arial", 24, "bold"))
90+
91+
elif self.game_state == "PAUSED":
92+
self.game_state = "PLAYING"
93+
self.game_text.clear()
94+
95+
elif self.game_state == "GAME_OVER":
96+
self.snake.reset()
97+
self.scoreboard.reset()
98+
self.delay = SLEEP_TIME
99+
self.level = 1
100+
self.countdown()
101+
self.game_state = "PLAYING"
84102

85103
def run(self):
86-
self.countdown() # Start countdown
104+
self.game_text.write("Press SPACEBAR to Start", align="center", font=("Arial", 24, "bold"))
87105

88106
while True:
89107
self.screen.update()
90108

91-
# Pause check
92-
if self.paused:
109+
if self.game_state in ["IDLE", "PAUSED", "GAME_OVER"]:
110+
time.sleep(0.1)
93111
continue
94112

95113
# Boundary collision
96114
if self.snake.check_boundary_collision():
97115
if self.pygame_installed:
98116
self.gameover_sound.play()
99-
self.snake.reset()
100-
self.scoreboard.reset()
101-
self.delay = SLEEP_TIME
102-
self.level = 1
117+
self.game_text.write("GAME OVER - Press SPACE to Restart", align="center", font=("Arial", 20, "bold"))
118+
self.game_state = "GAME_OVER"
119+
continue
103120

104121
# Food collision
105122
if self.snake.head.distance(self.food.item) < COLLISION_DISTANCE:
106123
self.food.reposition(self.snake)
107124
self.snake.add_part()
108-
109125
self.scoreboard.increase()
110126
if self.pygame_installed:
111127
self.eat_sound.play()
112128

113-
# Level system
114129
if self.scoreboard.score % 5 == 0:
115130
self.level += 1
116131
self.delay -= 0.01
117-
118-
# Optional level message
119-
self.scoreboard.show_message(f"LEVEL {self.level}")
132+
self.game_text.clear()
133+
self.game_text.write(f"LEVEL {self.level}", align="center", font=("Arial", 24, "bold"))
120134
self.screen.update()
121135
time.sleep(0.5)
122-
self.scoreboard.update_display()
136+
self.game_text.clear()
123137

124138
# Move snake
125139
self.snake.move()
@@ -128,12 +142,10 @@ def run(self):
128142
if self.snake.check_self_collision():
129143
if self.pygame_installed:
130144
self.gameover_sound.play()
131-
self.snake.reset()
132-
self.scoreboard.reset()
133-
self.delay = SLEEP_TIME
134-
self.level = 1
145+
self.game_text.write("GAME OVER - Press SPACE to Restart", align="center", font=("Arial", 20, "bold"))
146+
self.game_state = "GAME_OVER"
147+
continue
135148

136-
# Game speed
137149
time.sleep(self.delay)
138150

139151

@@ -142,4 +154,4 @@ def run(self):
142154
try:
143155
game.run()
144156
except turtle.Terminator:
145-
pass
157+
pass

0 commit comments

Comments
 (0)