93 lines
3.0 KiB
Python
93 lines
3.0 KiB
Python
"""Vorspann: Anleitungsbild und Startsequenz (Ampel + Reissverschluss).
|
||
|
||
Bewusst zwei getrennte Bausteine, damit die Reihenfolge im Hauptprogramm
|
||
eindeutig ist: **Anleitung → Moduswahl → Startsequenz → Spiel**.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import pygame
|
||
|
||
from . import config, scene
|
||
from .input_map import Action
|
||
|
||
|
||
class Tutorial:
|
||
"""Zeigt das Anleitungsbild und wartet auf A / Space.
|
||
|
||
Kommt vor jeder Runde – auch nach einem Ergebnis.
|
||
"""
|
||
|
||
def __init__(self, assets) -> None:
|
||
self.assets = assets
|
||
self.done = assets.instruction is None
|
||
|
||
def handle(self, action: Action) -> None:
|
||
if action is Action.PRIMARY:
|
||
self.done = True
|
||
|
||
def update(self, dt: float) -> bool:
|
||
return self.done
|
||
|
||
def draw(self, surface: pygame.Surface) -> None:
|
||
if self.assets.instruction is not None:
|
||
surface.blit(self.assets.instruction, (0, 0))
|
||
return
|
||
scene.draw_top_bar(surface, self.assets, 0.0)
|
||
scene.draw_background(surface, self.assets)
|
||
scene.clear_bottom_bar(surface)
|
||
|
||
|
||
class StartSequence:
|
||
"""Ampel (rot/gelb/grün) und Reissverschluss, der den Auflieger öffnet."""
|
||
|
||
def __init__(self, assets) -> None:
|
||
self.assets = assets
|
||
self.timer = 0.0
|
||
self.dot_index = 0
|
||
self.finished = False
|
||
self.assets.play("beep1")
|
||
|
||
def handle(self, action: Action) -> None:
|
||
"""Während der Startsequenz wird keine Eingabe gebraucht."""
|
||
|
||
def update(self, dt: float) -> bool:
|
||
self.timer += dt
|
||
if not self.finished:
|
||
index = int(self.timer // config.INTRO_DOT_DELAY)
|
||
if index >= len(config.INTRO_DOT_COLORS):
|
||
self.finished = True
|
||
self.timer = 0.0
|
||
self.assets.play("zip")
|
||
elif index != self.dot_index:
|
||
self.dot_index = index
|
||
self.assets.play(f"beep{index + 1}")
|
||
return False
|
||
return self.timer >= config.INTRO_ZIP_DURATION
|
||
|
||
def draw(self, surface: pygame.Surface) -> None:
|
||
scene.draw_top_bar(surface, self.assets, 0.0)
|
||
scene.draw_background(surface, self.assets)
|
||
scene.clear_bottom_bar(surface)
|
||
|
||
if not self.finished:
|
||
if 0 <= self.dot_index < len(config.INTRO_DOT_COLORS):
|
||
pygame.draw.circle(
|
||
surface,
|
||
config.INTRO_DOT_COLORS[self.dot_index],
|
||
(
|
||
config.TRAILER_X + config.TRAILER_WIDTH // 2,
|
||
config.TRAILER_Y + config.TRAILER_HEIGHT // 2,
|
||
),
|
||
config.INTRO_DOT_RADIUS,
|
||
)
|
||
else:
|
||
duration = config.INTRO_ZIP_DURATION or 1.0
|
||
progress = min(1.0, self.timer / duration)
|
||
width = int(config.TRAILER_WIDTH * progress)
|
||
pygame.draw.rect(
|
||
surface,
|
||
config.COLOR_TRAILER,
|
||
(config.TRAILER_X, config.TRAILER_Y, width, config.TRAILER_HEIGHT),
|
||
)
|