Skip to content

Commit e137ac5

Browse files
committed
fix: replace busy-wait loop with ontimer-driven ticks in Snake game
1 parent ecb99c8 commit e137ac5

1 file changed

Lines changed: 58 additions & 45 deletions

File tree

games/Snake-Game/main.py

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,20 @@ def handle_spacebar(self):
8282
if self.game_state == "IDLE":
8383
self.countdown()
8484
self.game_state = "PLAYING"
85+
# Schedule the first tick after spacebar is pressed
86+
self.screen.ontimer(self.tick, int(self.delay * 1000))
8587

8688
elif self.game_state == "PLAYING":
8789
self.game_state = "PAUSED"
8890
self.game_text.clear()
8991
self.game_text.write("PAUSED", align="center", font=("Arial", 24, "bold"))
92+
# Don't schedule next tick; game is paused
9093

9194
elif self.game_state == "PAUSED":
9295
self.game_state = "PLAYING"
9396
self.game_text.clear()
97+
# Resume ticking when unpaused
98+
self.screen.ontimer(self.tick, int(self.delay * 1000))
9499

95100
elif self.game_state == "GAME_OVER":
96101
self.snake.reset()
@@ -99,54 +104,62 @@ def handle_spacebar(self):
99104
self.level = 1
100105
self.countdown()
101106
self.game_state = "PLAYING"
107+
# Schedule the first tick after restart
108+
self.screen.ontimer(self.tick, int(self.delay * 1000))
109+
110+
def tick(self):
111+
"""Single game tick - called via ontimer() to avoid busy-waiting."""
112+
# Only process game logic if game is actively playing
113+
if self.game_state != "PLAYING":
114+
return
115+
116+
self.screen.update()
117+
118+
# Boundary collision
119+
if self.snake.check_boundary_collision():
120+
if self.pygame_installed:
121+
self.gameover_sound.play()
122+
self.game_text.write("GAME OVER - Press SPACE to Restart", align="center", font=("Arial", 20, "bold"))
123+
self.game_state = "GAME_OVER"
124+
return
125+
126+
# Food collision
127+
if self.snake.head.distance(self.food.item) < COLLISION_DISTANCE:
128+
self.food.reposition(self.snake)
129+
self.snake.add_part()
130+
self.scoreboard.increase()
131+
if self.pygame_installed:
132+
self.eat_sound.play()
133+
134+
if self.scoreboard.score % 5 == 0:
135+
self.level += 1
136+
self.delay -= 0.01
137+
self.game_text.clear()
138+
self.game_text.write(f"LEVEL {self.level}", align="center", font=("Arial", 24, "bold"))
139+
self.screen.update()
140+
time.sleep(0.5)
141+
self.game_text.clear()
142+
143+
# Move snake
144+
self.snake.move()
145+
146+
# Self collision
147+
if self.snake.check_self_collision():
148+
if self.pygame_installed:
149+
self.gameover_sound.play()
150+
self.game_text.write("GAME OVER - Press SPACE to Restart", align="center", font=("Arial", 20, "bold"))
151+
self.game_state = "GAME_OVER"
152+
return
153+
154+
# Schedule next tick
155+
self.screen.ontimer(self.tick, int(self.delay * 1000))
102156

103157
def run(self):
158+
"""Main entry point - display startup message and enter event loop."""
104159
self.game_text.write("Press SPACEBAR to Start", align="center", font=("Arial", 24, "bold"))
105-
106-
while True:
107-
self.screen.update()
108-
109-
if self.game_state in ["IDLE", "PAUSED", "GAME_OVER"]:
110-
time.sleep(0.1)
111-
continue
112-
113-
# Boundary collision
114-
if self.snake.check_boundary_collision():
115-
if self.pygame_installed:
116-
self.gameover_sound.play()
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
120-
121-
# Food collision
122-
if self.snake.head.distance(self.food.item) < COLLISION_DISTANCE:
123-
self.food.reposition(self.snake)
124-
self.snake.add_part()
125-
self.scoreboard.increase()
126-
if self.pygame_installed:
127-
self.eat_sound.play()
128-
129-
if self.scoreboard.score % 5 == 0:
130-
self.level += 1
131-
self.delay -= 0.01
132-
self.game_text.clear()
133-
self.game_text.write(f"LEVEL {self.level}", align="center", font=("Arial", 24, "bold"))
134-
self.screen.update()
135-
time.sleep(0.5)
136-
self.game_text.clear()
137-
138-
# Move snake
139-
self.snake.move()
140-
141-
# Self collision
142-
if self.snake.check_self_collision():
143-
if self.pygame_installed:
144-
self.gameover_sound.play()
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
148-
149-
time.sleep(self.delay)
160+
self.screen.update()
161+
# Turtle event loop keeps ontimer() callbacks running
162+
self.screen.mainloop()
150163

151164

152165
if __name__ == "__main__":

0 commit comments

Comments
 (0)