Altstand nach old_version/ eingefroren (untracked). Monolith ersetzt durch main.py + Paket loader_game/. Neu: run.sh/run.command mit venv+requirements, .gitignore, docs/ANALYSE.md, 35 Tests. Secrets entfernt. Gelöscht: loader_game.py, qr_scan*.py, INSTALL_README.txt.

This commit is contained in:
Project Bridge committed 2026-11-01 10:25:13 +00:00
1 parent 6a2c891c3e
commit de550e1d4d
24 files changed
+2269 -1008

No files matched your search

+108
View File
@@ -0,0 +1,108 @@
"""Tastatur und Controller → abstrakte Aktionen.
Die Aktionen sind absichtlich generisch gehalten. Die spätere Namenseingabe
per Controller benutzt dieselben Richtungen (Buchstabe weiter/zurück,
Position wechseln), deshalb gibt es hier keine spielspezifischen Namen.
"""
from __future__ import annotations
import enum
import pygame
from . import config
class Action(enum.Enum):
"""Abstrakte Eingabe – unabhängig davon, ob Tastatur oder Controller."""
PRIMARY = "primary" # Space / Enter / Controller A
LEFT = "left" # Pfeil links / D-Pad links
RIGHT = "right" # Pfeil rechts / D-Pad rechts
UP = "up" # Pfeil hoch / D-Pad hoch
DOWN = "down" # Pfeil runter / D-Pad runter
BACK = "back" # Esc / Controller B
#: Tastaturbelegung
KEY_ACTIONS: dict[int, Action] = {
pygame.K_SPACE: Action.PRIMARY,
pygame.K_RETURN: Action.PRIMARY,
pygame.K_KP_ENTER: Action.PRIMARY,
pygame.K_LEFT: Action.LEFT,
pygame.K_RIGHT: Action.RIGHT,
pygame.K_UP: Action.UP,
pygame.K_DOWN: Action.DOWN,
pygame.K_ESCAPE: Action.BACK,
}
#: Controller-Tasten (Xbox-Layout: 0=A, 1=B, 2=X, 3=Y)
BUTTON_ACTIONS: dict[int, Action] = {
0: Action.PRIMARY,
1: Action.BACK,
2: Action.LEFT,
3: Action.UP,
}
#: D-Pad, das als Hat gemeldet wird
HAT_ACTIONS: dict[tuple[int, int], Action] = {
(-1, 0): Action.LEFT,
(1, 0): Action.RIGHT,
(0, -1): Action.UP,
(0, 1): Action.DOWN,
}
#: Analogstick: ab diesem Ausschlag gilt eine Richtung als gewollt
AXIS_DEADZONE = 0.6
def actions_from_event(event: pygame.event.Event) -> list[Action]:
"""Übersetzt ein pygame-Event in null bis eine Aktion."""
if event.type == pygame.KEYDOWN:
action = KEY_ACTIONS.get(event.key)
return [action] if action else []
if event.type == pygame.JOYBUTTONDOWN:
action = BUTTON_ACTIONS.get(event.button)
return [action] if action else []
if event.type == pygame.JOYHATMOTION:
action = HAT_ACTIONS.get(tuple(event.value))
return [action] if action else []
if event.type == pygame.JOYAXISMOTION:
if event.axis == 0 and abs(event.value) >= AXIS_DEADZONE:
return [Action.RIGHT if event.value > 0 else Action.LEFT]
if event.axis == 1 and abs(event.value) >= AXIS_DEADZONE:
return [Action.DOWN if event.value > 0 else Action.UP]
return []
def connected_controllers() -> list[str]:
"""Namen aller angeschlossenen Controller (leer, wenn keiner da ist)."""
names = []
for index in range(pygame.joystick.get_count()):
try:
stick = pygame.joystick.Joystick(index)
stick.init()
names.append(stick.get_name())
except pygame.error:
continue
return names
def describe_controller_setup() -> str:
names = connected_controllers()
if not names:
return "Controller: keiner erkannt (Tastatur: Space=Snap, ←=Drehen, ↑=OnTop, Esc=Ende)"
return "Controller: " + ", ".join(names)
def controller_hint_lines() -> list[str]:
"""Kurzhilfe fürs Log beim Start."""
return [
describe_controller_setup(),
f"Zielauflösung {config.SCREEN_WIDTH}x{config.SCREEN_HEIGHT}, "
f"{config.FPS} fps",
]