Dialogue Box¶
NPC dialogue panel with a continue prompt.
▶ Run in browserTags: ui dialogue game-ui
What it demonstrates¶
A panel anchored across the bottom of the screen with
AnchorPreset.BOTTOM_WIDE.Speaker name + body text driven by a list of dialogue lines.
A “continue” button that advances through the lines and closes on the last one.
Top-level Controls use anchors + margins, never absolute position.
Run: uv run python examples/features/ui/dialog.py
Source¶
1"""Dialogue Box: NPC dialogue panel with a continue prompt.
2
3# /// simvx
4# tags = ["ui", "dialogue", "game-ui"]
5# web = { root = "DialogueDemo", width = 800, height = 600, responsive = true }
6# ///
7
8## What it demonstrates
9- A panel anchored across the bottom of the screen with `AnchorPreset.BOTTOM_WIDE`.
10- Speaker name + body text driven by a list of dialogue lines.
11- A "continue" button that advances through the lines and closes on the last one.
12- Top-level Controls use anchors + margins, never absolute position.
13
14Run: uv run python examples/features/ui/dialog.py
15"""
16
17from simvx.core import AnchorPreset, Colour, Label, Node, Panel, Vec2
18from simvx.core.ui import Button
19from simvx.graphics import App
20
21# A short scripted conversation: (speaker, line).
22LINES = [
23 ("Guide", "Welcome to the village, traveller."),
24 ("Guide", "The old mine to the north has been overrun."),
25 ("Guide", "Take this lantern. You will need its light."),
26 ("Guide", "Good luck out there. Come back safe."),
27]
28
29
30class DialogueDemo(Node):
31 """Root node: a bottom-anchored NPC dialogue box."""
32
33 def on_ready(self):
34 self._index = 0
35
36 # Bottom-anchored dialogue panel: full width, fixed height at the
37 # bottom edge. Margins inset it slightly from the screen edges.
38 panel = Panel(name="DialoguePanel")
39 panel.set_anchor_preset(AnchorPreset.BOTTOM_WIDE)
40 panel.margin_left = 20
41 panel.margin_right = -20
42 panel.margin_top = -180
43 panel.margin_bottom = -20
44 panel.bg_colour = Colour.hex("#15171F")
45 self.add_child(panel)
46
47 # Speaker name, top-left inside the panel.
48 self._speaker = Label(name="Speaker")
49 self._speaker.font_size = 18.0
50 self._speaker.text_colour = Colour.hex("#FFCC66")
51 self._speaker.set_anchor_preset(AnchorPreset.TOP_WIDE)
52 self._speaker.margin_left = 20
53 self._speaker.margin_right = -20
54 self._speaker.margin_top = 14
55 self._speaker.size_y = 24
56 panel.add_child(self._speaker)
57
58 # Body text, fills the remaining panel area.
59 self._body = Label(name="Body")
60 self._body.font_size = 15.0
61 self._body.text_colour = Colour.LIGHT_GRAY
62 self._body.set_anchor_preset(AnchorPreset.FULL_RECT)
63 self._body.margin_left = 20
64 self._body.margin_right = -20
65 self._body.margin_top = 48
66 self._body.margin_bottom = -56
67 panel.add_child(self._body)
68
69 # Continue button, bottom-right of the panel.
70 self._continue = Button("Continue", on_press=self._advance)
71 self._continue.set_anchor_preset(AnchorPreset.BOTTOM_RIGHT)
72 self._continue.size = Vec2(140, 32)
73 self._continue.margin_left = -160
74 self._continue.margin_top = -44
75 self._continue.margin_right = -20
76 self._continue.margin_bottom = -12
77 panel.add_child(self._continue)
78
79 self._panel = panel
80 self._show_current()
81
82 def _show_current(self):
83 """Render the dialogue line at the current index."""
84 speaker, text = LINES[self._index]
85 self._speaker.text = speaker
86 self._body.text = text
87 last = self._index == len(LINES) - 1
88 self._continue.text = "Close" if last else "Continue"
89
90 def _advance(self):
91 """Move to the next line, or close the box on the last line."""
92 if self._index >= len(LINES) - 1:
93 self._panel.visible = False
94 return
95 self._index += 1
96 self._show_current()
97
98
99if __name__ == "__main__":
100 App(title="SimVX Dialogue Box", width=800, height=600).run(DialogueDemo())