More effects and tweaks
This commit is contained in:
BIN
effects/over.mp3
Normal file
BIN
effects/over.mp3
Normal file
Binary file not shown.
BIN
effects/start.mp3
Normal file
BIN
effects/start.mp3
Normal file
Binary file not shown.
BIN
effects/start2.mp3
Normal file
BIN
effects/start2.mp3
Normal file
Binary file not shown.
BIN
effects/wall.mp3
Normal file
BIN
effects/wall.mp3
Normal file
Binary file not shown.
77
snake.py
77
snake.py
@@ -4,6 +4,7 @@ import time
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
import pygame
|
import pygame
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
import signal
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
@@ -18,6 +19,8 @@ class Game:
|
|||||||
# Defaults
|
# Defaults
|
||||||
self.snake_length = 3
|
self.snake_length = 3
|
||||||
self.snake_speed = 7
|
self.snake_speed = 7
|
||||||
|
self.enable_effects = True
|
||||||
|
self.enable_music = False
|
||||||
|
|
||||||
# Snake and food characters
|
# Snake and food characters
|
||||||
# ASCII Table: https://theasciicode.com.ar/
|
# ASCII Table: https://theasciicode.com.ar/
|
||||||
@@ -55,10 +58,8 @@ class Game:
|
|||||||
# Get terminal (screen) height and width
|
# Get terminal (screen) height and width
|
||||||
self.screen_height, self.screen_width = self.stdscr.getmaxyx()
|
self.screen_height, self.screen_width = self.stdscr.getmaxyx()
|
||||||
|
|
||||||
# Start Music
|
|
||||||
self.queue.put('music.start')
|
|
||||||
|
|
||||||
# Show selcome page
|
# Show selcome page
|
||||||
|
self.effect('start')
|
||||||
self.load_welcome()
|
self.load_welcome()
|
||||||
|
|
||||||
# Ask for snake length
|
# Ask for snake length
|
||||||
@@ -67,11 +68,21 @@ class Game:
|
|||||||
# Ask for snake speed
|
# Ask for snake speed
|
||||||
self.snake_speed = self.ask_question(f"Snake Speed (1 to 10, Default {self.snake_speed}): ", int, 7, 1, 10)
|
self.snake_speed = self.ask_question(f"Snake Speed (1 to 10, Default {self.snake_speed}): ", int, 7, 1, 10)
|
||||||
|
|
||||||
|
# Ask for Music
|
||||||
|
self.enable_music = (self.ask_question(f"Turn on Music (y/N): ", str, 'N')).upper() == 'Y'
|
||||||
|
|
||||||
|
# Ask for Effects
|
||||||
|
self.enable_effects = (self.ask_question(f"Turn on Sound Effects (Y/n): ", str, 'Y')).upper() == 'Y'
|
||||||
|
|
||||||
# Debug Inputs
|
# Debug Inputs
|
||||||
#self.print_center(f"Length: {self.snake_length}, Speed: {self.snake_speed}, Width: {self.screen_width}, Height: {self.screen_height}")
|
#self.print_center(f"Length: {self.snake_length}, Speed: {self.snake_speed}, Width: {self.screen_width}, Height: {self.screen_height}")
|
||||||
#time.sleep(2)
|
#time.sleep(2)
|
||||||
|
|
||||||
# Start Game!!!
|
# Start music
|
||||||
|
if self.enable_music:
|
||||||
|
self.queue.put('music.start')
|
||||||
|
|
||||||
|
# Start game!!!
|
||||||
self.start_game()
|
self.start_game()
|
||||||
|
|
||||||
|
|
||||||
@@ -181,19 +192,24 @@ class Game:
|
|||||||
#exit('yyyyy')
|
#exit('yyyyy')
|
||||||
#new_head = head
|
#new_head = head
|
||||||
|
|
||||||
# Check collisions
|
# Check wall collisions
|
||||||
if (new_head[0] in [0, self.screen_height - 1] or
|
if (new_head[0] in [0, self.screen_height - 1] or
|
||||||
new_head[1] in [0, self.screen_width - 1] or
|
new_head[1] in [0, self.screen_width - 1]):
|
||||||
new_head in snake):
|
# Crashed into wall, quit
|
||||||
# Crashed into something, show quit screen
|
self.effect('wall')
|
||||||
self.queue.put('effect.wall')
|
break
|
||||||
|
|
||||||
|
# Check self collisions
|
||||||
|
if new_head in snake:
|
||||||
|
# Crashed into self, quit
|
||||||
|
self.effect('self')
|
||||||
break
|
break
|
||||||
|
|
||||||
snake.insert(0, new_head)
|
snake.insert(0, new_head)
|
||||||
|
|
||||||
# Check if snake ate food
|
# Check if snake ate food
|
||||||
if snake[0] == food:
|
if snake[0] == food:
|
||||||
self.queue.put('effect.eat')
|
self.effect('eat')
|
||||||
score += 1
|
score += 1
|
||||||
food = get_new_food()
|
food = get_new_food()
|
||||||
else:
|
else:
|
||||||
@@ -219,6 +235,7 @@ class Game:
|
|||||||
self.refresh_screen()
|
self.refresh_screen()
|
||||||
|
|
||||||
# Game Over screen
|
# Game Over screen
|
||||||
|
self.effect('over')
|
||||||
self.print_center(f"GAME OVER! SCORE: {score}", 0, self.colors['red'])
|
self.print_center(f"GAME OVER! SCORE: {score}", 0, self.colors['red'])
|
||||||
self.print_center(f"(R)estart, or (Q)uit", 2, self.colors['green'])
|
self.print_center(f"(R)estart, or (Q)uit", 2, self.colors['green'])
|
||||||
self.stdscr.nodelay(0)
|
self.stdscr.nodelay(0)
|
||||||
@@ -241,7 +258,7 @@ class Game:
|
|||||||
self.refresh_screen()
|
self.refresh_screen()
|
||||||
|
|
||||||
|
|
||||||
def ask_question(self, question: str, value_type: Any, value_default: Any, value_min: int, value_max: int) -> Any:
|
def ask_question(self, question: str, value_type: Any, value_default: Any, value_min: int = 0, value_max: int = 0) -> Any:
|
||||||
# Make the cursor visible
|
# Make the cursor visible
|
||||||
curses.curs_set(1)
|
curses.curs_set(1)
|
||||||
|
|
||||||
@@ -291,6 +308,9 @@ class Game:
|
|||||||
self.print_center(f"ERROR: Must be an integer between {value_min} and {value_max}", 2, self.colors['red'])
|
self.print_center(f"ERROR: Must be an integer between {value_min} and {value_max}", 2, self.colors['red'])
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
self.ask_question(question, value_type, value_min, value_max)
|
self.ask_question(question, value_type, value_min, value_max)
|
||||||
|
else:
|
||||||
|
if not answer:
|
||||||
|
answer = value_default
|
||||||
|
|
||||||
return answer
|
return answer
|
||||||
|
|
||||||
@@ -322,6 +342,9 @@ class Game:
|
|||||||
self.queue.put('quit')
|
self.queue.put('quit')
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
def effect(self, effect):
|
||||||
|
if self.enable_effects:
|
||||||
|
self.queue.put(effect)
|
||||||
|
|
||||||
|
|
||||||
def main(stdscr, queue):
|
def main(stdscr, queue):
|
||||||
@@ -335,8 +358,10 @@ def sound_process(sound_queue):
|
|||||||
|
|
||||||
effects = {
|
effects = {
|
||||||
'eat': pygame.mixer.Sound('effects/bing.mp3'),
|
'eat': pygame.mixer.Sound('effects/bing.mp3'),
|
||||||
'wall': pygame.mixer.Sound('effects/cut.mp3'),
|
'wall': pygame.mixer.Sound('effects/wall.mp3'),
|
||||||
'self': pygame.mixer.Sound('effects/cut.mp3'),
|
'self': pygame.mixer.Sound('effects/cut.mp3'),
|
||||||
|
'over': pygame.mixer.Sound('effects/over.mp3'),
|
||||||
|
'start': pygame.mixer.Sound('effects/start2.mp3'),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load sounds/music (adjust file paths as needed)
|
# Load sounds/music (adjust file paths as needed)
|
||||||
@@ -348,25 +373,35 @@ def sound_process(sound_queue):
|
|||||||
while True:
|
while True:
|
||||||
if not sound_queue.empty():
|
if not sound_queue.empty():
|
||||||
command = sound_queue.get()
|
command = sound_queue.get()
|
||||||
if command == 'effect.eat':
|
|
||||||
effects['eat'].play()
|
# Play effects if requested
|
||||||
if command == 'effect.wall':
|
for effect, sound in effects.items():
|
||||||
effects['wall'].play()
|
if command == effect:
|
||||||
if command == 'effect.self':
|
sound.play()
|
||||||
effects['self'].play()
|
|
||||||
elif command == 'music.start':
|
# Play music
|
||||||
|
if command == 'music.start':
|
||||||
pygame.mixer.music.load(music_file)
|
pygame.mixer.music.load(music_file)
|
||||||
pygame.mixer.music.set_volume(0.25)
|
pygame.mixer.music.set_volume(0.25)
|
||||||
pygame.mixer.music.play(-1) # Play music indefinitely
|
pygame.mixer.music.play(-1) # Play music indefinitely
|
||||||
elif command == 'music.stop':
|
elif command == 'music.stop':
|
||||||
pygame.mixer.music.stop()
|
pygame.mixer.music.stop()
|
||||||
|
|
||||||
|
# Quit came
|
||||||
elif command == 'quit':
|
elif command == 'quit':
|
||||||
break
|
break
|
||||||
time.sleep(0.1) # Small delay to prevent high CPU usage
|
|
||||||
|
# Small delay to prevent high CPU usage
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
# Handle CTRL+C (uvicore also handles with Aborted! but this catches other odd cases)
|
||||||
|
signal.signal(signal.SIGINT, lambda sig, frame: exit())
|
||||||
|
|
||||||
# Create a queue for communication
|
# Create a queue for communication
|
||||||
queue = multiprocessing.Queue()
|
queue = multiprocessing.Queue()
|
||||||
|
|
||||||
@@ -376,5 +411,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# Start curses game loop
|
# Start curses game loop
|
||||||
game = curses.wrapper(main, queue)
|
game = curses.wrapper(main, queue)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user