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:
parent
99d26b7951
commit
576f4cc87a
51
__init__.py
51
__init__.py
@ -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]
|
||||
|
15
display.py
15
display.py
@ -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
208
menu.py
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user