From bce918166df61f3cee328599c37e1a57d5286038 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 23 Feb 2025 13:26:14 -0500 Subject: [PATCH] Various bug fixes. Intro sound working correctly. --- __init__.py | 98 +++++++++++++++++++++++++++++++++++++++++------------ display.py | 28 ++++++++++++--- speech.py | 6 ++-- 3 files changed, 103 insertions(+), 29 deletions(-) diff --git a/__init__.py b/__init__.py index 0d78b6c..1838590 100644 --- a/__init__.py +++ b/__init__.py @@ -4,26 +4,27 @@ Core initialization module for PygStormGames framework. Provides the main PygStormGames class that serves as the central hub for game functionality. """ +import pyglet +import time from .config import Config from .display import Display from .menu import Menu from .scoreboard import Scoreboard from .sound import Sound from .speech import Speech -import pyglet class pygstormgames: """Main class that coordinates all game systems.""" def __init__(self, gameTitle): """Initialize the game framework. - + Args: gameTitle (str): Title of the game """ self.gameTitle = gameTitle self._paused = False - + # Initialize core systems self.config = Config(gameTitle) self.display = Display(gameTitle) @@ -31,32 +32,24 @@ class pygstormgames: self.sound = Sound(self) self.scoreboard = Scoreboard(self) self.menu = Menu(self) - + # Play intro sound if available try: player = self.sound.play_sound('game-intro') if player: - # Wait for completion or skip input - @self.display.window.event - def on_key_press(symbol, modifiers): - if symbol in (pyglet.window.key.ESCAPE, - pyglet.window.key.RETURN, - pyglet.window.key.SPACE): - player.pause() - # Remove the temporary event handler - self.display.window.remove_handler('on_key_press', on_key_press) - return True - - # Wait for sound to finish or user to skip - while player.playing: - self.display.window.dispatch_events() - - # Remove the temporary event handler if not already removed - self.display.window.remove_handler('on_key_press', on_key_press) + startTime = time.time() + duration = player.source.duration + # Make sure to give pyglet enough cycles to start playing + pyglet.clock.tick() + interrupted = self.wait_for_completion( + lambda: not player.playing or (time.time() - startTime) >= duration + ) + if interrupted: + player.pause() except: pass - # Set up window event handlers + # Set up window event handlers after intro is complete self.display.window.push_handlers(self.on_key_press) def on_key_press(self, symbol, modifiers): @@ -95,3 +88,64 @@ class pygstormgames: self.sound.cleanup() self.speech.cleanup() pyglet.app.exit() + + def wait(self, valid_keys=None): + """Wait for key press(es). + + Args: + valid_keys (list, optional): List of pyglet.window.key values to wait for. + If None, accepts any key press. + + Returns: + int: The key that was pressed + """ + result = [None] # Use list to allow modification in closure + + def on_key_press(symbol, modifiers): + if valid_keys is None or symbol in valid_keys: + result[0] = symbol + return pyglet.event.EVENT_HANDLED + + # Register temporary handler + self.display.window.push_handlers(on_key_press=on_key_press) + + # Wait for valid key press + while result[0] is None: + self.display.window.dispatch_events() + pyglet.clock.tick() + + # Clean up + self.display.window.remove_handlers() + return result[0] + + def wait_for_completion(self, condition, validKeys=None): + """Wait for either a condition to be met or valid keys to be pressed. + + Args: + condition: Function that returns True when waiting should end + validKeys (list, optional): List of pyglet.window.key values that can interrupt + If None, uses ESCAPE, RETURN, and SPACE + + Returns: + bool: True if interrupted by key press, False if condition was met + """ + if validKeys is None: + validKeys = [pyglet.window.key.ESCAPE, + pyglet.window.key.RETURN, + pyglet.window.key.SPACE] + + wasInterrupted = [False] # Use list to allow modification in closure + + def on_key_press(symbol, modifiers): + if symbol in validKeys: + wasInterrupted[0] = True + return pyglet.event.EVENT_HANDLED + + self.display.window.push_handlers(on_key_press=on_key_press) + + while not condition() and not wasInterrupted[0]: + self.display.window.dispatch_events() + pyglet.clock.tick() + + self.display.window.remove_handlers() + return wasInterrupted[0] diff --git a/display.py b/display.py index 071d27b..a4235fe 100644 --- a/display.py +++ b/display.py @@ -114,19 +114,39 @@ class Display: self.display_text(info, speech) - def get_input(self, prompt="Enter text:", default_text=""): +def messagebox(self, text): + """Display a simple message box with text. + + Shows a message that can be repeated until the user chooses to continue. + + Args: + text (str): Message to display + """ + text = text + "\nPress any key to repeat or enter to continue." + while True: + # Speak the text + self.game.speech.speak(text) + + # Wait for any key + key = self.game.wait() + + # Exit if enter/escape pressed + if key in (pyglet.window.key.RETURN, pyglet.window.key.ESCAPE): + break + + def get_input(self, prompt="Enter text:", defaultText=""): """Display a dialog box for text input. Args: prompt (str): Prompt text to display - default_text (str): Initial text in input box + defaultText (str): Initial text in input box Returns: str: User input text, or None if cancelled """ app = wx.App(False) - dialog = wx.TextEntryDialog(None, prompt, "Input", default_text) - dialog.SetValue(default_text) + dialog = wx.TextEntryDialog(None, prompt, "Input", defaultText) + dialog.SetValue(defaultText) if dialog.ShowModal() == wx.ID_OK: userInput = dialog.GetValue() else: diff --git a/speech.py b/speech.py index 2b6221a..5a036c1 100644 --- a/speech.py +++ b/speech.py @@ -48,16 +48,16 @@ class Speech: text (str): Text to speak and display interrupt (bool): Whether to interrupt current speech """ - current_time = time.time() * 1000 + currentTime = time.time() * 1000 # Prevent rapid repeated messages if (self._lastSpoken["text"] == text and - current_time - self._lastSpoken["time"] < self._speechDelay): + currentTime - self._lastSpoken["time"] < self._speechDelay): return # Update last spoken tracking self._lastSpoken["text"] = text - self._lastSpoken["time"] = current_time + self._lastSpoken["time"] = currentTime # Handle speech output based on provider if self._provider == "speechd":