"""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 if title: self.game.speech.speak(title) 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 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.exit_game() return 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.""" 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 self.game.sound.pause_bgm() self.game.display.instructions(self.game.speech) # Resume menu music self.game.sound.resume_bgm() elif selection == "learn_sounds": if self.learn_sounds() == "menu": continue elif selection == "credits": # Pause menu music self.game.sound.pause_bgm() self.game.display.credits(self.game.speech) # Resume menu music self.game.sound.resume_bgm() elif selection == "donate": # Pause menu music self.game.sound.pause_bgm() self.game.display.donate(self.game.speech) # Resume menu music self.game.sound.resume_bgm() elif selection == "exit": 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 """ try: self.game.sound.currentBgm.pause() except: pass # Get list of available sounds, excluding music and ambiance directories soundList = self.game.sound.get_sound_list() if not soundList: self.game.speech.speak("No sounds available to learn.") return "menu" # Sort sounds by name soundList.sort() self.currentIndex = 0 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 instructions self.game.speech.speak("Learn game sounds. Use up and down arrow keys or W/S to navigate, Enter to play sound, Escape to exit.") # Speak initial sound name soundName = soundList[self.currentIndex] displayName = soundName.replace("/", " in folder ") self.game.speech.speak(f"Sound 1 of {len(soundList)}: {displayName}") while True: key, _ = self.game.wait(validKeys) if key == pyglet.window.key.ESCAPE: try: self.game.sound.currentBgm.play() except: pass return "menu" if key in [pyglet.window.key.DOWN, pyglet.window.key.S]: if self.currentIndex < len(soundList) - 1: self.game.sound.stop_all_sounds() self.currentIndex += 1 soundName = soundList[self.currentIndex] displayName = soundName.replace("/", " in folder ") self.game.speech.speak(f"Sound {self.currentIndex + 1} of {len(soundList)}: {displayName}") if key in [pyglet.window.key.UP, pyglet.window.key.W]: if self.currentIndex > 0: self.game.sound.stop_all_sounds() self.currentIndex -= 1 soundName = soundList[self.currentIndex] displayName = soundName.replace("/", " in folder ") self.game.speech.speak(f"Sound {self.currentIndex + 1} of {len(soundList)}: {displayName}") if key == pyglet.window.key.RETURN: soundName = soundList[self.currentIndex] self.game.sound.stop_all_sounds() self.game.sound.play_sound(soundName)