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)