v1.1: Stufen Easy/Normal/Hard mit Auswahlmenü (Hard = altes Tempo). Koffer behalten beim Drehen ihre Textur. Name/Punkteliste entfernt, nur Stufe + Prozent. Endlos: Ergebnis -> "Nochmals?" -> Stufenauswahl, Ende nur per Esc. storage.py und net.py gelöscht, 48 Tests.
This commit is contained in:
1 parent
de550e1d4d
commit
d970185e75
15 files changed
+613
-342
No files matched your search
@@ -0,0 +1,100 @@
|
||||
"""Startmenü: Schwierigkeitsstufe wählen (Easy / Normal / Hard)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pygame
|
||||
|
||||
from . import config, scene
|
||||
from .difficulty import DEFAULT_DIFFICULTY, DIFFICULTIES, Difficulty
|
||||
from .input_map import Action
|
||||
|
||||
|
||||
class DifficultyMenu:
|
||||
"""Drei Kacheln, Auswahl mit ← / →, Start mit A / Space."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
assets,
|
||||
options: tuple[Difficulty, ...] = DIFFICULTIES,
|
||||
selected: Difficulty = DEFAULT_DIFFICULTY,
|
||||
) -> None:
|
||||
self.assets = assets
|
||||
self.options = list(options)
|
||||
self.index = self.options.index(selected) if selected in self.options else 0
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
@property
|
||||
def selected(self) -> Difficulty:
|
||||
return self.options[self.index]
|
||||
|
||||
def handle(self, action: Action) -> Difficulty | None:
|
||||
"""Rückgabe: gewählte Stufe, sobald bestätigt wurde – sonst ``None``."""
|
||||
if action is Action.LEFT:
|
||||
self.index = (self.index - 1) % len(self.options)
|
||||
elif action is Action.RIGHT:
|
||||
self.index = (self.index + 1) % len(self.options)
|
||||
elif action is Action.PRIMARY:
|
||||
return self.selected
|
||||
return None
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
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)
|
||||
scene.draw_dim(surface, 170)
|
||||
|
||||
font = self.assets.font
|
||||
small = self.assets.font_small or font
|
||||
|
||||
title = font.render(config.MENU_TITLE, True, config.COLOR_WHITE)
|
||||
surface.blit(
|
||||
title,
|
||||
(config.SCREEN_WIDTH // 2 - title.get_width() // 2, config.MENU_TOP - 110),
|
||||
)
|
||||
|
||||
total_width = len(self.options) * config.MENU_BOX_WIDTH + (
|
||||
len(self.options) - 1
|
||||
) * config.MENU_BOX_GAP
|
||||
x = (config.SCREEN_WIDTH - total_width) // 2
|
||||
|
||||
for index, difficulty in enumerate(self.options):
|
||||
rect = pygame.Rect(
|
||||
x, config.MENU_TOP, config.MENU_BOX_WIDTH, config.MENU_BOX_HEIGHT
|
||||
)
|
||||
active = index == self.index
|
||||
pygame.draw.rect(
|
||||
surface,
|
||||
config.COLOR_MENU_BOX_ACTIVE if active else config.COLOR_MENU_BOX,
|
||||
rect,
|
||||
border_radius=14,
|
||||
)
|
||||
pygame.draw.rect(
|
||||
surface,
|
||||
config.COLOR_WHITE if active else config.COLOR_MENU_BORDER,
|
||||
rect,
|
||||
width=config.MENU_BOX_BORDER,
|
||||
border_radius=14,
|
||||
)
|
||||
label = font.render(
|
||||
difficulty.label, True, (0, 0, 0) if active else config.COLOR_WHITE
|
||||
)
|
||||
surface.blit(
|
||||
label,
|
||||
(
|
||||
rect.centerx - label.get_width() // 2,
|
||||
rect.centery - label.get_height() // 2,
|
||||
),
|
||||
)
|
||||
x += config.MENU_BOX_WIDTH + config.MENU_BOX_GAP
|
||||
|
||||
hint = small.render(config.MENU_HINT, True, config.COLOR_WHITE)
|
||||
hint_y = config.MENU_TOP + config.MENU_BOX_HEIGHT + 60
|
||||
band = pygame.Rect(
|
||||
config.SCREEN_WIDTH // 2 - hint.get_width() // 2 - 30,
|
||||
hint_y - 10,
|
||||
hint.get_width() + 60,
|
||||
hint.get_height() + 20,
|
||||
)
|
||||
pygame.draw.rect(surface, config.COLOR_DIM, band, border_radius=10)
|
||||
surface.blit(hint, (band.x + 30, hint_y))
|
||||
Reference in new issue
Block a user