"""Menu system module for PygStormGames. Handles main menu and submenu functionality for games. """ import os import pyglet from os.path import isfile, join from pyglet.window import key class Menu: """Handles menu systems.""" def __init__(self, game): """Initialize menu system. Args: game (PygStormGames): Reference to main game object """ self.game = game self.currentIndex = 0 def show_menu(self, options, title=None, with_music=False): """Display a menu and return selected option.""" if with_music: try: if self.game.sound.currentBgm: self.game.sound.currentBgm.pause() self.game.sound.play_bgm("sounds/music_menu.ogg") except: pass 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: 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 def game_menu(self): """Show main game menu.""" options = [ "play", "instructions", "learn_sounds", "credits", "donate", "exit" ] while True: selection = self.show_menu(options, with_music=True) if selection == "play": return selection elif selection == "instructions": # Pause menu music if self.game.sound.currentBgm: self.game.sound.currentBgm.pause() self.game.display.instructions(self.game.speech) # Resume menu music if self.game.sound.currentBgm: self.game.sound.currentBgm.play() elif selection == "learn_sounds": if self.learn_sounds() == "menu": continue elif selection == "credits": # Pause menu music if self.game.sound.currentBgm: self.game.sound.currentBgm.pause() self.game.display.credits(self.game.speech) # Resume menu music if self.game.sound.currentBgm: self.game.sound.currentBgm.play() elif selection == "donate": # Pause menu music if self.game.sound.currentBgm: self.game.sound.currentBgm.pause() self.game.display.donate(self.game.speech) # Resume menu music if self.game.sound.currentBgm: self.game.sound.currentBgm.play() 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 """ try: self.game.sound.currentBgm.pause() except: pass self.currentIndex = 0 # Get list of available sounds, excluding special sounds soundFiles = [f for f in os.listdir("sounds/") if isfile(join("sounds/", f)) 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: try: self.game.sound.currentBgm.unpause() 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] self.game.sound.stop_all_sounds() self.game.sound.play_sound(soundName) except: lastSpoken = -1 self.game.speech.speak("Could not play sound.")