nodes/menu.pyΒΆ
Part of Clear Code Zelda.
1"""Title screen: shown before the level so the game opens on a menu.
2
3Starting from a menu also gives the browser the user gesture it wants before
4any audio plays, so the soundtrack can start with the level.
5"""
6
7from __future__ import annotations
8
9from settings import TEXT_COLOUR, UI_BG_COLOUR, UI_BORDER_COLOUR_ACTIVE
10
11from simvx.core import Input, MouseButton, Node2D, Signal
12
13BACKDROP_COLOUR = (0.05, 0.08, 0.06, 1.0)
14DIM_TEXT_COLOUR = (0.62, 0.66, 0.62, 1.0)
15
16CONTROLS = [
17 "WASD / arrows walk",
18 "SPACE sword attack",
19 "CTRL cast the selected spell",
20 "Q / E swap weapon / spell",
21 "M upgrade screen",
22 "ESC quit",
23 "",
24 "On touch or mouse: drag the left-hand stick to walk,",
25 "tap ATK / MAG / Q / E / M on the right.",
26]
27
28
29class StartScreen(Node2D):
30 """Title card. ENTER, SPACE or a click begins the game."""
31
32 # The prompt blinks off a timer, which is not a Property.
33 dynamic = True
34
35 start_requested = Signal()
36
37 def __init__(self, **kwargs):
38 super().__init__(name="StartScreen", **kwargs)
39 self.z_index = 2000
40 self._blink = 0.0
41
42 def on_update(self, dt: float):
43 self._blink += dt
44 if Input.is_mouse_button_just_pressed(MouseButton.LEFT) or Input.is_action_just_pressed("ui_select"):
45 self.start_requested()
46
47 def on_draw(self, renderer):
48 sw, sh = self.tree.screen_size if self.tree else (1280.0, 720.0)
49 renderer.draw_rect((0, 0), (sw, sh), colour=BACKDROP_COLOUR, filled=True)
50
51 title = "CLEAR CODE ZELDA"
52 tw = renderer.text_width(title, 4.0)
53 renderer.draw_text(title, ((sw - tw) / 2, sh * 0.16), colour=TEXT_COLOUR, scale=4.0)
54
55 sub = "A SimVX port of Clear Code's Pygame ARPG tutorial"
56 sww = renderer.text_width(sub, 1.6)
57 renderer.draw_text(sub, ((sw - sww) / 2, sh * 0.16 + 72), colour=DIM_TEXT_COLOUR, scale=1.6)
58
59 # The panel is sized from its widest line, so nothing spills over its edge.
60 line_scale = 1.4
61 panel_w = max(renderer.text_width(line, line_scale) for line in CONTROLS) + 48
62 panel_h = 26 * len(CONTROLS) + 32
63 panel_x = (sw - panel_w) / 2
64 panel_y = sh * 0.34
65 renderer.draw_rect((panel_x, panel_y), (panel_w, panel_h), colour=UI_BG_COLOUR, filled=True)
66 for i, line in enumerate(CONTROLS):
67 renderer.draw_text(line, (panel_x + 24, panel_y + 20 + i * 26), colour=TEXT_COLOUR, scale=line_scale)
68
69 if int(self._blink * 2) % 2 == 0:
70 prompt = "PRESS SPACE / ENTER OR CLICK TO PLAY"
71 pw = renderer.text_width(prompt, 2.0)
72 renderer.draw_text(prompt, ((sw - pw) / 2, sh * 0.86), colour=UI_BORDER_COLOUR_ACTIVE, scale=2.0)