More effects and tweaks

This commit is contained in:
2026-03-12 08:50:21 -06:00
parent 009527dc89
commit f1845e044e
5 changed files with 64 additions and 27 deletions

BIN
effects/over.mp3 Normal file

Binary file not shown.

BIN
effects/start.mp3 Normal file

Binary file not shown.

BIN
effects/start2.mp3 Normal file

Binary file not shown.

BIN
effects/wall.mp3 Normal file

Binary file not shown.

View File

@@ -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,33 +373,45 @@ 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__":
# Create a queue for communication try:
queue = multiprocessing.Queue()
# Start the sound process # Handle CTRL+C (uvicore also handles with Aborted! but this catches other odd cases)
p = multiprocessing.Process(target=sound_process, args=(queue,)) signal.signal(signal.SIGINT, lambda sig, frame: exit())
p.start()
# Start curses game loop # Create a queue for communication
game = curses.wrapper(main, queue) queue = multiprocessing.Queue()
# Start the sound process
p = multiprocessing.Process(target=sound_process, args=(queue,))
p.start()
# Start curses game loop
game = curses.wrapper(main, queue)
except KeyboardInterrupt:
exit(0)