Files
libstormgames/input.py
2025-07-10 01:22:24 -04:00

245 lines
8.2 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Input handling for Storm Games.
Provides functionality for:
- Text input dialogs
- Game pause functionality
- Exit handling
"""
import pygame
import time
from .speech import speak
def get_input(prompt="Enter text:", text=""):
"""Display an accessible text input dialog using pygame.
Features:
- Speaks each character as typed
- Left/Right arrows navigate and speak characters
- Up/Down arrows read full text content
- Backspace announces deletions
- Enter submits, Escape cancels
- Control key repeats the original prompt message
- Fully accessible without screen reader dependency
Args:
prompt (str): Prompt text to display (default: "Enter text:")
text (str): Initial text in input box (default: "")
Returns:
str: User input text, or None if cancelled
"""
# Initialize text buffer and cursor
text_buffer = list(text) # Use list for easier character manipulation
cursor_pos = len(text_buffer) # Start at end of initial text
# Announce the prompt and initial text as a single message
if text:
initial_message = f"{prompt} Default text: {text}"
else:
initial_message = f"{prompt} Empty text field"
speak(initial_message)
# Main input loop
while True:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
# Submit the input
result = ''.join(text_buffer)
speak(f"Submitted: {result if result else 'empty'}")
return result
elif event.key == pygame.K_ESCAPE:
# Cancel input
speak("Cancelled")
return None
elif event.key == pygame.K_BACKSPACE:
# Delete character before cursor
if cursor_pos > 0:
deleted_char = text_buffer.pop(cursor_pos - 1)
cursor_pos -= 1
speak(f"{deleted_char} deleted")
else:
speak("Nothing to delete")
elif event.key == pygame.K_DELETE:
# Delete character at cursor
if cursor_pos < len(text_buffer):
deleted_char = text_buffer.pop(cursor_pos)
speak(f"{deleted_char} deleted")
else:
speak("Nothing to delete")
elif event.key == pygame.K_LEFT:
# Move cursor left and speak character
if cursor_pos > 0:
cursor_pos -= 1
if cursor_pos == 0:
speak("Beginning of text")
else:
speak(text_buffer[cursor_pos])
else:
speak("Beginning of text")
elif event.key == pygame.K_RIGHT:
# Move cursor right and speak character
if cursor_pos < len(text_buffer):
speak(text_buffer[cursor_pos])
cursor_pos += 1
if cursor_pos == len(text_buffer):
speak("End of text")
else:
speak("End of text")
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
# Read entire text content
if text_buffer:
speak(''.join(text_buffer))
else:
speak("Empty text field")
elif event.key == pygame.K_HOME:
# Move to beginning
cursor_pos = 0
speak("Beginning of text")
elif event.key == pygame.K_END:
# Move to end
cursor_pos = len(text_buffer)
speak("End of text")
elif event.key == pygame.K_LCTRL or event.key == pygame.K_RCTRL:
# Repeat the original prompt message
speak(initial_message)
else:
# Handle regular character input
if event.unicode and event.unicode.isprintable():
char = event.unicode
# Insert character at cursor position
text_buffer.insert(cursor_pos, char)
cursor_pos += 1
# Speak the character name
if char == ' ':
speak("space")
elif char == '\\':
speak("backslash")
elif char == '/':
speak("slash")
elif char == '!':
speak("exclamation mark")
elif char == '"':
speak("quotation mark")
elif char == '#':
speak("hash")
elif char == '$':
speak("dollar sign")
elif char == '%':
speak("percent")
elif char == '&':
speak("ampersand")
elif char == "'":
speak("apostrophe")
elif char == '(':
speak("left parenthesis")
elif char == ')':
speak("right parenthesis")
elif char == '*':
speak("asterisk")
elif char == '+':
speak("plus")
elif char == ',':
speak("comma")
elif char == '-':
speak("minus")
elif char == '.':
speak("period")
elif char == ':':
speak("colon")
elif char == ';':
speak("semicolon")
elif char == '<':
speak("less than")
elif char == '=':
speak("equals")
elif char == '>':
speak("greater than")
elif char == '?':
speak("question mark")
elif char == '@':
speak("at sign")
elif char == '[':
speak("left bracket")
elif char == ']':
speak("right bracket")
elif char == '^':
speak("caret")
elif char == '_':
speak("underscore")
elif char == '`':
speak("grave accent")
elif char == '{':
speak("left brace")
elif char == '|':
speak("pipe")
elif char == '}':
speak("right brace")
elif char == '~':
speak("tilde")
else:
# For regular letters, numbers, and other characters
speak(char)
# Allow other events to be processed
pygame.event.pump()
def pause_game():
"""Pauses the game until user presses backspace."""
speak("Game paused, press backspace to resume.")
pygame.event.clear()
try:
pygame.mixer.pause()
except:
pass
try:
pygame.mixer.music.pause()
except:
pass
while True:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN and event.key == pygame.K_BACKSPACE:
break
try:
pygame.mixer.unpause()
except:
pass
try:
pygame.mixer.music.unpause()
except:
pass
pygame.event.pump()
def check_for_exit():
"""Check if user has pressed escape key.
Returns:
bool: True if escape was pressed, False otherwise
"""
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
return True
return False
pygame.event.pump()