nodes/hud.pyΒΆ

Part of GDQuest Open RPG.

 1"""Front-of-game title card plus the persistent bottom controls strip."""
 2
 3from __future__ import annotations
 4
 5from simvx.core import Node2D
 6from simvx.core.input.state import Input
 7from simvx.core.signals import Signal
 8
 9from .settings import PANEL_BORDER, PANEL_BORDER_FOCUS, TEXT, TEXT_DIM
10
11TITLE_LINE = "OPEN RPG"
12SUBTITLE_LINE = "a SimVX port of GDQuest's godot-open-rpg"
13
14HOW_TO = [
15    "WASD, arrows, D-pad or the on-screen pad    walk one tile at a time",
16    "Tap a tile                                  walk there along a BFS path",
17    "E, (A) or the pad's button                  talk to whoever you are facing",
18    "Red tiles                                   wild encounters, yellow shrine saves",
19    "Q or (Back)                                 quit",
20]
21
22
23class TitleScreen(Node2D):
24    """Full-viewport title card. Emits ``started`` on confirm or click."""
25
26    def __init__(self) -> None:
27        super().__init__()
28        self.z_index = 9000
29        self.started = Signal()
30
31    def on_update(self, dt: float) -> None:
32        if Input.just_pressed("advance"):
33            self.started.emit()
34            self.destroy()
35
36    def on_draw(self, renderer) -> None:
37        w, h = self.viewport_size
38        renderer.rect((0, 0), (w, h), fill=(0.05, 0.06, 0.10, 0.94))
39
40        cx = w * 0.5
41        title_y = h * 0.16
42        renderer.text(
43            TITLE_LINE, (cx - renderer.text_width(TITLE_LINE, 4.0) * 0.5, title_y), fill=PANEL_BORDER_FOCUS, scale=4.0
44        )
45        renderer.text(
46            SUBTITLE_LINE, (cx - renderer.text_width(SUBTITLE_LINE, 1.2) * 0.5, title_y + 60), fill=TEXT_DIM, scale=1.2
47        )
48
49        # How-to block: left-aligned as one column so the key names line up.
50        block_w = max(renderer.text_width(line, 1.2) for line in HOW_TO)
51        x = cx - block_w * 0.5
52        y = h * 0.40
53        for line in HOW_TO:
54            renderer.text(line, (x, y), fill=TEXT, scale=1.2)
55            y += 30
56
57        prompt = "ENTER, SPACE, (A) or tap to begin"
58        renderer.text(
59            prompt, (cx - renderer.text_width(prompt, 1.6) * 0.5, h - 110), fill=PANEL_BORDER_FOCUS, scale=1.6
60        )
61
62
63class ControlsStrip(Node2D):
64    """Thin bar pinned to the bottom of the viewport listing the live controls."""
65
66    BAR_HEIGHT = 26
67
68    def __init__(self) -> None:
69        super().__init__()
70        self.z_index = 4000
71        self._hint = ""
72
73    @property
74    def hint(self) -> str:
75        """Control legend currently shown. Assigning a new one re-draws the bar."""
76        return self._hint
77
78    @hint.setter
79    def hint(self, value: str) -> None:
80        if value != self._hint:
81            self._hint = value
82            self.queue_redraw()
83
84    def on_draw(self, renderer) -> None:
85        if not self._hint:
86            return
87        w, h = self.viewport_size
88        y = h - self.BAR_HEIGHT
89        renderer.rect((0, y), (w, self.BAR_HEIGHT), fill=(0.06, 0.07, 0.11, 0.88))
90        renderer.rect((0, y), (w, 1), fill=PANEL_BORDER)
91        renderer.text(self._hint, (14, y + 7), fill=TEXT_DIM, scale=1.0)