More bug fixes, modified wait methods to send modifiers too. Only show text nav instructions the first time desplay_text() is used.

This commit is contained in:
Storm Dragon 2025-02-23 14:51:49 -05:00
parent 99d26b7951
commit 576f4cc87a
3 changed files with 149 additions and 125 deletions

View File

@ -89,43 +89,44 @@ class pygstormgames:
self.speech.cleanup()
pyglet.app.exit()
def wait(self, valid_keys=None):
def wait(self, validKeys=None):
"""Wait for key press(es).
Args:
valid_keys (list, optional): List of pyglet.window.key values to wait for.
validKeys (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
tuple: (key, modifiers) that were pressed
"""
keyResult = [None, 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
if validKeys is None or symbol in validKeys:
keyResult[0] = symbol
keyResult[1] = modifiers
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:
while keyResult[0] is None:
self.display.window.dispatch_events()
pyglet.clock.tick()
# Clean up
self.display.window.remove_handlers()
return result[0]
return tuple(keyResult)
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
"""
@ -133,19 +134,19 @@ class pygstormgames:
validKeys = [pyglet.window.key.ESCAPE,
pyglet.window.key.RETURN,
pyglet.window.key.SPACE]
wasInterrupted = [False] # Use list to allow modification in closure
interrupted = [False] # Use list to allow modification in closure
def on_key_press(symbol, modifiers):
if symbol in validKeys:
wasInterrupted[0] = True
interrupted[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]:
while not condition() and not interrupted[0]:
self.display.window.dispatch_events()
pyglet.clock.tick()
self.display.window.remove_handlers()
return wasInterrupted[0]
return interrupted[0]

View File

@ -25,6 +25,7 @@ class Display:
"""
self.game = game
self.window = pyglet.window.Window(800, 600, caption=game.gameTitle)
self.displayedInstructions = False
self.currentText = []
self.currentIndex = 0
self.gameTitle = game.gameTitle
@ -43,10 +44,12 @@ class Display:
self.navText = [line for line in text if line.strip()]
# Add instructions at start
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.")
self.navText.insert(0, instructions)
if not self.displayedInstructions:
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.")
self.navText.insert(0, instructions)
self.displayedInstructions = True
# Add end marker
self.navText.append("End of text.")
@ -68,7 +71,7 @@ class Display:
]
while True:
key = self.game.wait(validKeys)
key, _ = self.game.wait(validKeys)
if key in (pyglet.window.key.ESCAPE, pyglet.window.key.RETURN):
break
@ -142,7 +145,7 @@ def messagebox(self, text):
self.game.speech.speak(text)
# Wait for any key
key = self.game.wait()
key, _ = self.game.wait()
# Exit if enter/escape pressed
if key in (pyglet.window.key.RETURN, pyglet.window.key.ESCAPE):

208
menu.py
View File

@ -32,73 +32,81 @@ class Menu:
self.currentIndex = 0
lastSpoken = -1
selection = None # Add this to store the selection
if title:
self.game.speech.speak(title)
def key_handler(symbol, modifiers): # Define handler outside event
nonlocal selection, lastSpoken
# Handle Alt+volume controls
if modifiers & key.MOD_ALT:
if symbol == key.PAGEUP:
self.game.sound.adjust_master_volume(0.1)
elif symbol == key.PAGEDOWN:
self.game.sound.adjust_master_volume(-0.1)
elif symbol == key.HOME:
self.game.sound.adjust_bgm_volume(0.1)
elif symbol == key.END:
self.game.sound.adjust_bgm_volume(-0.1)
elif symbol == key.INSERT:
self.game.sound.adjust_sfx_volume(0.1)
elif symbol == key.DELETE:
self.game.sound.adjust_sfx_volume(-0.1)
return
if symbol == key.ESCAPE:
selection = "exit"
return pyglet.event.EVENT_HANDLED
if symbol == key.HOME and self.currentIndex != 0:
self.currentIndex = 0
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif symbol == key.END and self.currentIndex != len(options) - 1:
self.currentIndex = len(options) - 1
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif symbol in (key.DOWN, key.S) and self.currentIndex < len(options) - 1:
self.currentIndex += 1
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif symbol in (key.UP, key.W) and self.currentIndex > 0:
self.currentIndex -= 1
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif symbol == key.RETURN:
self.game.sound.play_sound('menu-select')
selection = options[self.currentIndex]
return pyglet.event.EVENT_HANDLED
return pyglet.event.EVENT_HANDLED
# Register the handler
self.game.display.window.push_handlers(on_key_press=key_handler)
# Main menu loop
while selection is None:
validKeys = [
pyglet.window.key.ESCAPE,
pyglet.window.key.RETURN,
pyglet.window.key.UP,
pyglet.window.key.DOWN,
pyglet.window.key.W,
pyglet.window.key.S,
pyglet.window.key.HOME,
pyglet.window.key.END,
pyglet.window.key.PAGEUP,
pyglet.window.key.PAGEDOWN,
pyglet.window.key.INSERT,
pyglet.window.key.DELETE
]
while True:
# Speak current option if changed
if self.currentIndex != lastSpoken:
self.game.speech.speak(options[self.currentIndex])
lastSpoken = self.currentIndex
self.game.display.window.dispatch_events()
# Clean up
self.game.display.window.remove_handlers()
return selection
key, keyModifiers = self.game.wait(validKeys)
# Handle Alt+volume controls
if keyModifiers & pyglet.window.key.MOD_ALT:
if key == pyglet.window.key.PAGEUP:
self.game.sound.adjust_master_volume(0.1)
elif key == pyglet.window.key.PAGEDOWN:
self.game.sound.adjust_master_volume(-0.1)
elif key == pyglet.window.key.HOME:
self.game.sound.adjust_bgm_volume(0.1)
elif key == pyglet.window.key.END:
self.game.sound.adjust_bgm_volume(-0.1)
elif key == pyglet.window.key.INSERT:
self.game.sound.adjust_sfx_volume(0.1)
elif key == pyglet.window.key.DELETE:
self.game.sound.adjust_sfx_volume(-0.1)
continue
if key == pyglet.window.key.ESCAPE:
if "exit" in options:
# Handle exit cleanup immediately
self.game.sound.cleanup()
self.game.display.window.remove_handlers()
self.game.speech.cleanup()
pyglet.app.exit()
return "exit"
if key == pyglet.window.key.HOME and self.currentIndex != 0:
self.currentIndex = 0
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif key == pyglet.window.key.END and self.currentIndex != len(options) - 1:
self.currentIndex = len(options) - 1
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif key in (pyglet.window.key.DOWN, pyglet.window.key.S) and self.currentIndex < len(options) - 1:
self.currentIndex += 1
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif key in (pyglet.window.key.UP, pyglet.window.key.W) and self.currentIndex > 0:
self.currentIndex -= 1
self.game.sound.play_sound('menu-move')
lastSpoken = -1 # Force speech
elif key == pyglet.window.key.RETURN:
self.game.sound.play_sound('menu-select')
return options[self.currentIndex]
def game_menu(self):
"""Show main game menu."""
@ -153,14 +161,20 @@ class Menu:
if self.game.sound.currentBgm:
self.game.sound.currentBgm.play()
elif selection == "exit":
self.game.sound.cleanup() # Stop all sounds first
self.game.display.window.remove_handlers() # Remove handlers before closing speech
self.game.speech.cleanup() # Clean up speech last
self.game.exit_game()
def learn_sounds(self):
"""Interactive menu for learning game sounds.
Allows users to:
- Navigate through available sounds
- Play selected sounds
- Return to menu with escape key
Returns:
str: "menu" if user exits with escape
"""
@ -177,40 +191,46 @@ class Menu:
and (f.split('.')[1].lower() in ["ogg", "wav"])
and (f.split('.')[0].lower() not in ["game-intro", "music_menu"])
and (not f.lower().startswith("_"))]
# Track last spoken index to avoid repetition
lastSpoken = -1
while True:
if self.currentIndex != lastSpoken:
self.game.speech.speak(soundFiles[self.currentIndex][:-4])
lastSpoken = self.currentIndex
event = self.game.display.window.dispatch_events()
@self.game.display.window.event
def on_key_press(symbol, modifiers):
if symbol == key.ESCAPE:
if not soundFiles:
self.game.speech.speak("No sounds available to learn.")
return "menu"
validKeys = [
pyglet.window.key.ESCAPE,
pyglet.window.key.RETURN,
pyglet.window.key.UP,
pyglet.window.key.DOWN,
pyglet.window.key.W,
pyglet.window.key.S
]
# Speak initial sound name
self.game.speech.speak(soundFiles[self.currentIndex][:-4])
while True:
key, _ = self.game.wait(validKeys)
if key == pyglet.window.key.ESCAPE:
try:
self.game.sound.currentBgm.unpause()
self.game.sound.currentBgm.play()
except:
pass
self.game.display.window.remove_handler('on_key_press', on_key_press)
return "menu"
if symbol in [key.DOWN, key.S] and self.currentIndex < len(soundFiles) - 1:
self.game.sound.stop_all_sounds()
self.currentIndex += 1
if symbol in [key.UP, key.W] and self.currentIndex > 0:
self.game.sound.stop_all_sounds()
self.currentIndex -= 1
if symbol == key.RETURN:
try:
soundName = soundFiles[self.currentIndex][:-4]
if key in [pyglet.window.key.DOWN, pyglet.window.key.S]:
if self.currentIndex < len(soundFiles) - 1:
self.game.sound.stop_all_sounds()
self.game.sound.play_sound(soundName)
except:
lastSpoken = -1
self.game.speech.speak("Could not play sound.")
self.currentIndex += 1
self.game.speech.speak(soundFiles[self.currentIndex][:-4])
if key in [pyglet.window.key.UP, pyglet.window.key.W]:
if self.currentIndex > 0:
self.game.sound.stop_all_sounds()
self.currentIndex -= 1
self.game.speech.speak(soundFiles[self.currentIndex][:-4])
if key == pyglet.window.key.RETURN:
soundName = soundFiles[self.currentIndex][:-4]
self.game.sound.stop_all_sounds()
self.game.sound.play_sound(soundName)