Attempt to fix traceback on game exit with some older games.
This commit is contained in:
114
utils.py
114
utils.py
@ -36,10 +36,10 @@ class Game:
|
||||
self.title = title
|
||||
|
||||
# Initialize services
|
||||
self.path_service = PathService.get_instance().initialize(title)
|
||||
self.config_service = ConfigService.get_instance()
|
||||
self.config_service.set_game_info(title, self.path_service)
|
||||
self.volume_service = VolumeService.get_instance()
|
||||
self.pathService = PathService.get_instance().initialize(title)
|
||||
self.configService = ConfigService.get_instance()
|
||||
self.configService.set_game_info(title, self.pathService)
|
||||
self.volumeService = VolumeService.get_instance()
|
||||
|
||||
# Initialize game components (lazy loaded)
|
||||
self._speech = None
|
||||
@ -47,7 +47,7 @@ class Game:
|
||||
self._scoreboard = None
|
||||
|
||||
# Display text instructions flag
|
||||
self.display_text_usage_instructions = False
|
||||
self.displayTextUsageInstructions = False
|
||||
|
||||
@property
|
||||
def speech(self):
|
||||
@ -68,7 +68,7 @@ class Game:
|
||||
Sound: Sound system instance
|
||||
"""
|
||||
if not self._sound:
|
||||
self._sound = Sound("sounds/", self.volume_service)
|
||||
self._sound = Sound("sounds/", self.volumeService)
|
||||
return self._sound
|
||||
|
||||
@property
|
||||
@ -79,7 +79,7 @@ class Game:
|
||||
Scoreboard: Scoreboard instance
|
||||
"""
|
||||
if not self._scoreboard:
|
||||
self._scoreboard = Scoreboard(self.config_service)
|
||||
self._scoreboard = Scoreboard(self.configService)
|
||||
return self._scoreboard
|
||||
|
||||
def initialize(self):
|
||||
@ -130,89 +130,89 @@ class Game:
|
||||
self.speech.speak(text, interrupt)
|
||||
return self
|
||||
|
||||
def play_bgm(self, music_file):
|
||||
def play_bgm(self, musicFile):
|
||||
"""Play background music.
|
||||
|
||||
Args:
|
||||
music_file (str): Path to music file
|
||||
musicFile (str): Path to music file
|
||||
|
||||
Returns:
|
||||
Game: Self for method chaining
|
||||
"""
|
||||
self.sound.play_bgm(music_file)
|
||||
self.sound.play_bgm(musicFile)
|
||||
return self
|
||||
|
||||
def display_text(self, text_lines):
|
||||
def display_text(self, textLines):
|
||||
"""Display text with navigation controls.
|
||||
|
||||
Args:
|
||||
text_lines (list): List of text lines
|
||||
textLines (list): List of text lines
|
||||
|
||||
Returns:
|
||||
Game: Self for method chaining
|
||||
"""
|
||||
# Store original text with blank lines for copying
|
||||
original_text = text_lines.copy()
|
||||
originalText = textLines.copy()
|
||||
|
||||
# Create navigation text by filtering out blank lines
|
||||
nav_text = [line for line in text_lines if line.strip()]
|
||||
navText = [line for line in textLines if line.strip()]
|
||||
|
||||
# Add instructions at the start on the first display
|
||||
if not self.display_text_usage_instructions:
|
||||
if not self.displayTextUsageInstructions:
|
||||
instructions = ("Press space to read the whole text. Use up and down arrows to navigate "
|
||||
"the text line by line. Press c to copy the current line to the clipboard "
|
||||
"or t to copy the entire text. Press enter or escape when you are done reading.")
|
||||
nav_text.insert(0, instructions)
|
||||
self.display_text_usage_instructions = True
|
||||
navText.insert(0, instructions)
|
||||
self.displayTextUsageInstructions = True
|
||||
|
||||
# Add end marker
|
||||
nav_text.append("End of text.")
|
||||
navText.append("End of text.")
|
||||
|
||||
current_index = 0
|
||||
self.speech.speak(nav_text[current_index])
|
||||
currentIndex = 0
|
||||
self.speech.speak(navText[currentIndex])
|
||||
|
||||
while True:
|
||||
event = pygame.event.wait()
|
||||
if event.type == pygame.KEYDOWN:
|
||||
# Check for Alt modifier
|
||||
mods = pygame.key.get_mods()
|
||||
alt_pressed = mods & pygame.KMOD_ALT
|
||||
altPressed = mods & pygame.KMOD_ALT
|
||||
|
||||
# Volume controls (require Alt)
|
||||
if alt_pressed:
|
||||
if altPressed:
|
||||
if event.key == pygame.K_PAGEUP:
|
||||
self.volume_service.adjust_master_volume(0.1, pygame.mixer)
|
||||
self.volumeService.adjust_master_volume(0.1, pygame.mixer)
|
||||
elif event.key == pygame.K_PAGEDOWN:
|
||||
self.volume_service.adjust_master_volume(-0.1, pygame.mixer)
|
||||
self.volumeService.adjust_master_volume(-0.1, pygame.mixer)
|
||||
elif event.key == pygame.K_HOME:
|
||||
self.volume_service.adjust_bgm_volume(0.1, pygame.mixer)
|
||||
self.volumeService.adjust_bgm_volume(0.1, pygame.mixer)
|
||||
elif event.key == pygame.K_END:
|
||||
self.volume_service.adjust_bgm_volume(-0.1, pygame.mixer)
|
||||
self.volumeService.adjust_bgm_volume(-0.1, pygame.mixer)
|
||||
elif event.key == pygame.K_INSERT:
|
||||
self.volume_service.adjust_sfx_volume(0.1, pygame.mixer)
|
||||
self.volumeService.adjust_sfx_volume(0.1, pygame.mixer)
|
||||
elif event.key == pygame.K_DELETE:
|
||||
self.volume_service.adjust_sfx_volume(-0.1, pygame.mixer)
|
||||
self.volumeService.adjust_sfx_volume(-0.1, pygame.mixer)
|
||||
else:
|
||||
if event.key in (pygame.K_ESCAPE, pygame.K_RETURN):
|
||||
return self
|
||||
|
||||
if event.key in [pygame.K_DOWN, pygame.K_s] and current_index < len(nav_text) - 1:
|
||||
current_index += 1
|
||||
self.speech.speak(nav_text[current_index])
|
||||
if event.key in [pygame.K_DOWN, pygame.K_s] and currentIndex < len(navText) - 1:
|
||||
currentIndex += 1
|
||||
self.speech.speak(navText[currentIndex])
|
||||
|
||||
if event.key in [pygame.K_UP, pygame.K_w] and current_index > 0:
|
||||
current_index -= 1
|
||||
self.speech.speak(nav_text[current_index])
|
||||
if event.key in [pygame.K_UP, pygame.K_w] and currentIndex > 0:
|
||||
currentIndex -= 1
|
||||
self.speech.speak(navText[currentIndex])
|
||||
|
||||
if event.key == pygame.K_SPACE:
|
||||
# Join with newlines to preserve spacing in speech
|
||||
self.speech.speak('\n'.join(original_text[1:-1]))
|
||||
self.speech.speak('\n'.join(originalText[1:-1]))
|
||||
|
||||
if event.key == pygame.K_c:
|
||||
try:
|
||||
import pyperclip
|
||||
pyperclip.copy(nav_text[current_index])
|
||||
self.speech.speak("Copied " + nav_text[current_index] + " to the clipboard.")
|
||||
pyperclip.copy(navText[currentIndex])
|
||||
self.speech.speak("Copied " + navText[currentIndex] + " to the clipboard.")
|
||||
except:
|
||||
self.speech.speak("Failed to copy the text to the clipboard.")
|
||||
|
||||
@ -220,7 +220,7 @@ class Game:
|
||||
try:
|
||||
import pyperclip
|
||||
# Join with newlines to preserve blank lines in full text
|
||||
pyperclip.copy(''.join(original_text[2:-1]))
|
||||
pyperclip.copy(''.join(originalText[2:-1]))
|
||||
self.speech.speak("Copied entire message to the clipboard.")
|
||||
except:
|
||||
self.speech.speak("Failed to copy the text to the clipboard.")
|
||||
@ -239,12 +239,12 @@ class Game:
|
||||
|
||||
# Utility functions
|
||||
|
||||
def check_for_updates(current_version, game_name, url):
|
||||
def check_for_updates(currentVersion, gameName, url):
|
||||
"""Check for game updates.
|
||||
|
||||
Args:
|
||||
current_version (str): Current version string (e.g. "1.0.0")
|
||||
game_name (str): Name of the game
|
||||
currentVersion (str): Current version string (e.g. "1.0.0")
|
||||
gameName (str): Name of the game
|
||||
url (str): URL to check for updates
|
||||
|
||||
Returns:
|
||||
@ -254,7 +254,7 @@ def check_for_updates(current_version, game_name, url):
|
||||
response = requests.get(url, timeout=5)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if 'version' in data and data['version'] > current_version:
|
||||
if 'version' in data and data['version'] > currentVersion:
|
||||
return {
|
||||
'version': data['version'],
|
||||
'url': data.get('url', ''),
|
||||
@ -264,29 +264,29 @@ def check_for_updates(current_version, game_name, url):
|
||||
print(f"Error checking for updates: {e}")
|
||||
return None
|
||||
|
||||
def get_version_tuple(version_str):
|
||||
def get_version_tuple(versionStr):
|
||||
"""Convert version string to comparable tuple.
|
||||
|
||||
Args:
|
||||
version_str (str): Version string (e.g. "1.0.0")
|
||||
versionStr (str): Version string (e.g. "1.0.0")
|
||||
|
||||
Returns:
|
||||
tuple: Version as tuple of integers
|
||||
"""
|
||||
return tuple(map(int, version_str.split('.')))
|
||||
return tuple(map(int, versionStr.split('.')))
|
||||
|
||||
def check_compatibility(required_version, current_version):
|
||||
def check_compatibility(requiredVersion, currentVersion):
|
||||
"""Check if current version meets minimum required version.
|
||||
|
||||
Args:
|
||||
required_version (str): Minimum required version string
|
||||
current_version (str): Current version string
|
||||
requiredVersion (str): Minimum required version string
|
||||
currentVersion (str): Current version string
|
||||
|
||||
Returns:
|
||||
bool: True if compatible, False otherwise
|
||||
"""
|
||||
req = get_version_tuple(required_version)
|
||||
cur = get_version_tuple(current_version)
|
||||
req = get_version_tuple(requiredVersion)
|
||||
cur = get_version_tuple(currentVersion)
|
||||
return cur >= req
|
||||
|
||||
def sanitize_filename(filename):
|
||||
@ -350,25 +350,25 @@ def distance_2d(x1, y1, x2, y2):
|
||||
"""
|
||||
return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
|
||||
|
||||
def generate_tone(frequency, duration=0.1, sample_rate=44100, volume=0.2):
|
||||
def generate_tone(frequency, duration=0.1, sampleRate=44100, volume=0.2):
|
||||
"""Generate a tone at the specified frequency.
|
||||
|
||||
Args:
|
||||
frequency (float): Frequency in Hz
|
||||
duration (float): Duration in seconds (default: 0.1)
|
||||
sample_rate (int): Sample rate in Hz (default: 44100)
|
||||
sampleRate (int): Sample rate in Hz (default: 44100)
|
||||
volume (float): Volume from 0.0 to 1.0 (default: 0.2)
|
||||
|
||||
Returns:
|
||||
pygame.mixer.Sound: Sound object with the generated tone
|
||||
"""
|
||||
|
||||
t = np.linspace(0, duration, int(sample_rate * duration), False)
|
||||
t = np.linspace(0, duration, int(sampleRate * duration), False)
|
||||
tone = np.sin(2 * np.pi * frequency * t)
|
||||
stereo_tone = np.vstack((tone, tone)).T # Create a 2D array for stereo
|
||||
stereo_tone = (stereo_tone * 32767 * volume).astype(np.int16) # Apply volume
|
||||
stereo_tone = np.ascontiguousarray(stereo_tone) # Ensure C-contiguous array
|
||||
return pygame.sndarray.make_sound(stereo_tone)
|
||||
stereoTone = np.vstack((tone, tone)).T # Create a 2D array for stereo
|
||||
stereoTone = (stereoTone * 32767 * volume).astype(np.int16) # Apply volume
|
||||
stereoTone = np.ascontiguousarray(stereoTone) # Ensure C-contiguous array
|
||||
return pygame.sndarray.make_sound(stereoTone)
|
||||
|
||||
def x_powerbar():
|
||||
"""Sound based horizontal power bar
|
||||
|
Reference in New Issue
Block a user