101 lines
3.5 KiB
Python
101 lines
3.5 KiB
Python
"""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))
|