105 lines
3.4 KiB
Python
105 lines
3.4 KiB
Python
"""Sound and music management."""
|
|
import time
|
|
import pygame
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
from multiprocessing import Queue
|
|
|
|
|
|
class SoundManager:
|
|
"""Manages sound effects and music in a separate process."""
|
|
|
|
def __init__(self):
|
|
self.sounds = {}
|
|
self.music_file: Optional[str] = None
|
|
self.effects_dir = Path(__file__).parent / 'effects'
|
|
self.music_dir = Path(__file__).parent / 'music'
|
|
|
|
def initialize(self) -> None:
|
|
"""Initialize pygame mixer."""
|
|
pygame.mixer.init()
|
|
self._load_effects()
|
|
self._load_music()
|
|
|
|
def _load_effects(self) -> None:
|
|
"""Load all sound effects."""
|
|
effect_files = {
|
|
'eat': 'bing.mp3',
|
|
'wall': 'wall.mp3',
|
|
'self': 'cut.mp3',
|
|
'over': 'over.mp3',
|
|
'start': 'start2.mp3',
|
|
}
|
|
|
|
for effect_name, filename in effect_files.items():
|
|
effect_path = self.effects_dir / filename
|
|
try:
|
|
if effect_path.exists():
|
|
self.sounds[effect_name] = pygame.mixer.Sound(str(effect_path))
|
|
except pygame.error as e:
|
|
print(f"Warning: Could not load effect {filename}: {e}")
|
|
|
|
def _load_music(self) -> None:
|
|
"""Load background music."""
|
|
# Try different music files in order of preference
|
|
music_options = ['bubbles.ogg', 'QonsVivaEveryone.mp3']
|
|
for filename in music_options:
|
|
music_path = self.music_dir / filename
|
|
if music_path.exists():
|
|
self.music_file = str(music_path)
|
|
break
|
|
|
|
def play_effect(self, effect_name: str) -> None:
|
|
"""Play a sound effect."""
|
|
if effect_name in self.sounds:
|
|
try:
|
|
self.sounds[effect_name].play()
|
|
except pygame.error as e:
|
|
print(f"Warning: Could not play effect {effect_name}: {e}")
|
|
|
|
def start_music(self) -> None:
|
|
"""Start playing background music."""
|
|
if self.music_file:
|
|
try:
|
|
pygame.mixer.music.load(self.music_file)
|
|
pygame.mixer.music.set_volume(0.5)
|
|
pygame.mixer.music.play(-1)
|
|
except pygame.error as e:
|
|
print(f"Warning: Could not play music: {e}")
|
|
|
|
def stop_music(self) -> None:
|
|
"""Stop playing music."""
|
|
pygame.mixer.music.stop()
|
|
|
|
def pause_music(self) -> None:
|
|
"""Pause music."""
|
|
pygame.mixer.music.pause()
|
|
|
|
def unpause_music(self) -> None:
|
|
"""Resume music."""
|
|
pygame.mixer.music.unpause()
|
|
|
|
def process_queue(self, sound_queue: Queue) -> None:
|
|
"""Main loop for processing sound commands from the queue."""
|
|
self.initialize()
|
|
|
|
while True:
|
|
if not sound_queue.empty():
|
|
command = sound_queue.get()
|
|
|
|
# Handle various commands
|
|
if command in self.sounds:
|
|
self.play_effect(command)
|
|
elif command == 'music.start':
|
|
self.start_music()
|
|
elif command == 'music.stop':
|
|
self.stop_music()
|
|
elif command == 'music.pause':
|
|
self.pause_music()
|
|
elif command == 'music.unpause':
|
|
self.unpause_music()
|
|
elif command == 'quit':
|
|
break
|
|
|
|
time.sleep(0.1)
|