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