Compare commits
4 Commits
ca2d0d34bd
...
f2079261d1
| Author | SHA1 | Date | |
|---|---|---|---|
| f2079261d1 | |||
| 0190fa3a06 | |||
| 09421c4bda | |||
| dcd204e476 |
+2
-2
@@ -51,7 +51,7 @@ from .input import get_input, check_for_exit, pause_game
|
||||
from .display import display_text, initialize_gui
|
||||
|
||||
# Import menu functions
|
||||
from .menu import game_menu, learn_sounds, instructions, credits, donate, exit_game
|
||||
from .menu import game_menu, instruction_menu, learn_sounds, instructions, credits, donate, exit_game
|
||||
|
||||
# Update imports to reference Scoreboard methods
|
||||
high_scores = Scoreboard.display_high_scores
|
||||
@@ -113,7 +113,7 @@ __all__ = [
|
||||
'display_text', 'initialize_gui',
|
||||
|
||||
# Menu
|
||||
'game_menu', 'learn_sounds', 'instructions', 'credits', 'donate', 'exit_game', 'high_scores', 'has_high_scores',
|
||||
'game_menu', 'instruction_menu', 'learn_sounds', 'instructions', 'credits', 'donate', 'exit_game', 'high_scores', 'has_high_scores',
|
||||
|
||||
# Game class
|
||||
'Game',
|
||||
|
||||
+49
-3
@@ -88,13 +88,55 @@ def initialize_gui(gameTitle):
|
||||
Speech.get_instance().speak("Error loading sounds.", False)
|
||||
soundData = {}
|
||||
|
||||
# Play intro sound if available
|
||||
# Play intro sound if available, optionally with visual logo
|
||||
from .sound import cut_scene
|
||||
if 'game-intro' in soundData:
|
||||
cut_scene(soundData, 'game-intro')
|
||||
_show_logo_with_audio(soundData, 'game-intro')
|
||||
|
||||
return soundData
|
||||
|
||||
def _show_logo_with_audio(soundData, audioKey):
|
||||
"""Show visual logo while playing audio intro.
|
||||
|
||||
Args:
|
||||
soundData (dict): Dictionary of loaded sounds
|
||||
audioKey (str): Key of the audio to play
|
||||
"""
|
||||
# Look for logo image files in common formats
|
||||
logoFiles = ['logo.png', 'logo.jpg', 'logo.jpeg', 'logo.gif', 'logo.bmp']
|
||||
logoImage = None
|
||||
|
||||
for logoFile in logoFiles:
|
||||
if os.path.exists(logoFile):
|
||||
try:
|
||||
logoImage = pygame.image.load(logoFile)
|
||||
break
|
||||
except pygame.error:
|
||||
continue
|
||||
|
||||
if logoImage:
|
||||
# Display logo while audio plays
|
||||
screen = pygame.display.get_surface()
|
||||
screenRect = screen.get_rect()
|
||||
logoRect = logoImage.get_rect(center=screenRect.center)
|
||||
|
||||
# Clear screen to black
|
||||
screen.fill((0, 0, 0))
|
||||
screen.blit(logoImage, logoRect)
|
||||
pygame.display.flip()
|
||||
|
||||
# Play audio and wait for it to finish
|
||||
from .sound import cut_scene
|
||||
cut_scene(soundData, audioKey)
|
||||
|
||||
# Clear screen after audio finishes
|
||||
screen.fill((0, 0, 0))
|
||||
pygame.display.flip()
|
||||
else:
|
||||
# No logo image found, just play audio
|
||||
from .sound import cut_scene
|
||||
cut_scene(soundData, audioKey)
|
||||
|
||||
def display_text(text):
|
||||
"""Display and speak text with navigation controls.
|
||||
|
||||
@@ -135,6 +177,9 @@ def display_text(text):
|
||||
|
||||
currentIndex = 0
|
||||
speech.speak(navText[currentIndex])
|
||||
|
||||
# Clear any pending events
|
||||
pygame.event.clear()
|
||||
|
||||
while True:
|
||||
event = pygame.event.wait()
|
||||
@@ -188,5 +233,6 @@ def display_text(text):
|
||||
except:
|
||||
speech.speak("Failed to copy the text to the clipboard.")
|
||||
|
||||
event = pygame.event.clear()
|
||||
pygame.event.pump()
|
||||
pygame.event.clear()
|
||||
time.sleep(0.001)
|
||||
|
||||
@@ -43,6 +43,9 @@ def get_input(prompt="Enter text:", text=""):
|
||||
initial_message = f"{prompt} Empty text field"
|
||||
speak(initial_message)
|
||||
|
||||
# Clear any pending events
|
||||
pygame.event.clear()
|
||||
|
||||
# Main input loop
|
||||
while True:
|
||||
event = pygame.event.wait()
|
||||
@@ -199,6 +202,8 @@ def get_input(prompt="Enter text:", text=""):
|
||||
|
||||
# Allow other events to be processed
|
||||
pygame.event.pump()
|
||||
pygame.event.clear()
|
||||
time.sleep(0.001)
|
||||
|
||||
def pause_game():
|
||||
"""Pauses the game until user presses backspace."""
|
||||
@@ -218,6 +223,10 @@ def pause_game():
|
||||
event = pygame.event.wait()
|
||||
if event.type == pygame.KEYDOWN and event.key == pygame.K_BACKSPACE:
|
||||
break
|
||||
|
||||
pygame.event.pump()
|
||||
pygame.event.clear()
|
||||
time.sleep(0.001)
|
||||
|
||||
try:
|
||||
pygame.mixer.unpause()
|
||||
|
||||
@@ -25,6 +25,94 @@ from .display import display_text
|
||||
from .scoreboard import Scoreboard
|
||||
from .services import PathService, ConfigService
|
||||
|
||||
def instruction_menu(sounds, instruction_text, *options):
|
||||
"""Display a menu with an instruction announcement at the top.
|
||||
|
||||
The instruction text is announced as item 0 but is not selectable.
|
||||
The actual menu items start at index 1, and navigation skips the instruction.
|
||||
|
||||
Args:
|
||||
sounds (dict): Dictionary of sound objects
|
||||
instruction_text (str): The instruction/context text to announce
|
||||
*options: Menu options to display
|
||||
|
||||
Returns:
|
||||
str: Selected menu option or None if cancelled
|
||||
"""
|
||||
# Get speech instance
|
||||
speech = Speech.get_instance()
|
||||
|
||||
# Create combined list with instruction at index 0
|
||||
all_items = [instruction_text] + list(options)
|
||||
|
||||
loop = True
|
||||
pygame.mixer.stop()
|
||||
current_index = 0 # Start at instruction
|
||||
last_spoken = -1
|
||||
|
||||
# Clear any pending events
|
||||
pygame.event.clear()
|
||||
|
||||
while loop:
|
||||
if current_index != last_spoken:
|
||||
speech.speak(all_items[current_index])
|
||||
last_spoken = current_index
|
||||
|
||||
event = pygame.event.wait()
|
||||
if event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_ESCAPE:
|
||||
return None
|
||||
elif event.key in [pygame.K_DOWN, pygame.K_s]:
|
||||
moved = False
|
||||
if current_index == 0: # On instruction, go to first menu item
|
||||
current_index = 1
|
||||
moved = True
|
||||
elif current_index < len(all_items) - 1: # Normal navigation
|
||||
current_index += 1
|
||||
moved = True
|
||||
|
||||
if moved:
|
||||
try:
|
||||
sounds['menu-move'].play()
|
||||
except:
|
||||
pass
|
||||
elif event.key in [pygame.K_UP, pygame.K_w]:
|
||||
if current_index > 1: # Can move up from menu items (but not to instruction)
|
||||
current_index -= 1
|
||||
try:
|
||||
sounds['menu-move'].play()
|
||||
except:
|
||||
pass
|
||||
elif event.key == pygame.K_HOME:
|
||||
target_index = 1 if current_index != 1 else current_index # Go to first menu item
|
||||
if target_index != current_index:
|
||||
current_index = target_index
|
||||
try:
|
||||
sounds['menu-move'].play()
|
||||
except:
|
||||
pass
|
||||
elif event.key == pygame.K_END and current_index != len(all_items) - 1:
|
||||
current_index = len(all_items) - 1
|
||||
try:
|
||||
sounds['menu-move'].play()
|
||||
except:
|
||||
pass
|
||||
elif event.key == pygame.K_RETURN:
|
||||
if current_index == 0: # Can't select the instruction
|
||||
continue
|
||||
try:
|
||||
sounds['menu-select'].play()
|
||||
time.sleep(sounds['menu-select'].get_length())
|
||||
except:
|
||||
pass
|
||||
return options[current_index - 1] # Adjust for instruction offset
|
||||
elif event.type == pygame.QUIT:
|
||||
return None
|
||||
|
||||
pygame.event.pump()
|
||||
pygame.event.clear()
|
||||
time.sleep(0.001)
|
||||
|
||||
def game_menu(sounds, playCallback=None, *customOptions):
|
||||
"""Display and handle the main game menu with standard and custom options.
|
||||
|
||||
@@ -96,6 +184,7 @@ def game_menu(sounds, playCallback=None, *customOptions):
|
||||
pygame.mixer.stop()
|
||||
currentIndex = 0
|
||||
lastSpoken = -1 # Track last spoken index
|
||||
pygame.event.clear()
|
||||
|
||||
while loop:
|
||||
if currentIndex != lastSpoken:
|
||||
@@ -249,7 +338,8 @@ def game_menu(sounds, playCallback=None, *customOptions):
|
||||
pass
|
||||
return allOptions[currentIndex]
|
||||
|
||||
event = pygame.event.clear()
|
||||
pygame.event.pump()
|
||||
pygame.event.clear()
|
||||
time.sleep(0.001)
|
||||
|
||||
def learn_sounds(sounds):
|
||||
@@ -334,6 +424,7 @@ def learn_sounds(sounds):
|
||||
|
||||
# Flag to track when to exit the loop
|
||||
returnToMenu = False
|
||||
pygame.event.clear()
|
||||
|
||||
while not returnToMenu:
|
||||
# Announce current sound
|
||||
@@ -442,9 +533,9 @@ def credits():
|
||||
def donate():
|
||||
"""Open the donation webpage.
|
||||
|
||||
Opens the Ko-fi donation page.
|
||||
Opens the donation page.
|
||||
"""
|
||||
webbrowser.open('https://ko-fi.com/stormux')
|
||||
webbrowser.open('https://www.paypal.com/donate/?business=stormdragon2976@gmail.com&no_recurring=0¤cy_code=USD')
|
||||
messagebox("The donation page has been opened in your browser.")
|
||||
|
||||
def exit_game(fade=0):
|
||||
|
||||
@@ -73,6 +73,8 @@ class Sound:
|
||||
if event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_RETURN, pygame.K_SPACE]:
|
||||
pygame.mixer.stop()
|
||||
return None
|
||||
pygame.event.pump()
|
||||
pygame.event.clear()
|
||||
pygame.time.delay(10)
|
||||
|
||||
return None
|
||||
@@ -335,6 +337,8 @@ def _play_cutscene(sound, sounds=None):
|
||||
if event.type == pygame.KEYDOWN and event.key in [pygame.K_ESCAPE, pygame.K_RETURN, pygame.K_SPACE]:
|
||||
pygame.mixer.stop()
|
||||
return None
|
||||
pygame.event.pump()
|
||||
pygame.event.clear()
|
||||
pygame.time.delay(10)
|
||||
|
||||
return None
|
||||
|
||||
@@ -111,12 +111,51 @@ class Game:
|
||||
# Load sound effects
|
||||
self.sound
|
||||
|
||||
# Play intro sound if available
|
||||
# Play intro sound if available, optionally with visual logo
|
||||
if 'game-intro' in self.sound.sounds:
|
||||
self.sound.cut_scene('game-intro')
|
||||
self._show_logo_with_audio('game-intro')
|
||||
|
||||
return self
|
||||
|
||||
def _show_logo_with_audio(self, audioKey):
|
||||
"""Show visual logo while playing audio intro.
|
||||
|
||||
Args:
|
||||
audioKey (str): Key of the audio to play
|
||||
"""
|
||||
# Look for logo image files in common formats
|
||||
logoFiles = ['logo.png', 'logo.jpg', 'logo.jpeg', 'logo.gif', 'logo.bmp']
|
||||
logoImage = None
|
||||
|
||||
for logoFile in logoFiles:
|
||||
if os.path.exists(logoFile):
|
||||
try:
|
||||
logoImage = pygame.image.load(logoFile)
|
||||
break
|
||||
except pygame.error:
|
||||
continue
|
||||
|
||||
if logoImage:
|
||||
# Display logo while audio plays
|
||||
screen = pygame.display.get_surface()
|
||||
screenRect = screen.get_rect()
|
||||
logoRect = logoImage.get_rect(center=screenRect.center)
|
||||
|
||||
# Clear screen to black
|
||||
screen.fill((0, 0, 0))
|
||||
screen.blit(logoImage, logoRect)
|
||||
pygame.display.flip()
|
||||
|
||||
# Play audio and wait for it to finish
|
||||
self.sound.cut_scene(audioKey)
|
||||
|
||||
# Clear screen after audio finishes
|
||||
screen.fill((0, 0, 0))
|
||||
pygame.display.flip()
|
||||
else:
|
||||
# No logo image found, just play audio
|
||||
self.sound.cut_scene(audioKey)
|
||||
|
||||
def speak(self, text, interrupt=True):
|
||||
"""Speak text using the speech system.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user