Splash Screen¶
the branded boot splash and a reusable loading screen.
▶ Run in browserTags: ui splash loading branding
Every windowed SimVX game boots behind the engine’s SplashScreen: it fades in
from black, shows the SIMVX wordmark over a faint grid with a segmented progress
bar, and fades back out onto the scene once the first frame is ready. It holds
for at least one second, so a fast machine never sees it flicker. App sets it
up: splash=None (the default) shows it on a windowed run, splash=False turns
it off, a SplashScreen instance replaces it, and splash_min_time= changes the
minimum hold.
The same control is a loading screen for a heavy scene change. Add it as the last
child so it draws over everything, and hand progress either a () -> float
returning 0..1 or any object with a .progress attribute, such as an asset
BatchHandle. set_progress(fraction, caption) sets the line under the bar.
The splash stays up until loading reaches 1.0 and its min_display_time has
passed; with skippable=True any key, click or tap after loading ends the hold
early. When it has faded off the scene it emits finished, which is where the
game tears it down.
Here each press of L, or a click or tap, loads the next level behind a splash
that fakes a 2.5 second load off tree.now. The animated background shows the
splash covering a running scene and fading back onto it in a new colour.
Source¶
1# /// simvx
2# tags = ["ui", "splash", "loading", "branding"]
3# web = { width = 800, height = 600, responsive = true }
4# ///
5"""Splash Screen: the branded boot splash and a reusable loading screen.
6
7Every windowed SimVX game boots behind the engine's `SplashScreen`: it fades in
8from black, shows the SIMVX wordmark over a faint grid with a segmented progress
9bar, and fades back out onto the scene once the first frame is ready. It holds
10for at least one second, so a fast machine never sees it flicker. `App` sets it
11up: `splash=None` (the default) shows it on a windowed run, `splash=False` turns
12it off, a `SplashScreen` instance replaces it, and `splash_min_time=` changes the
13minimum hold.
14
15The same control is a loading screen for a heavy scene change. Add it as the last
16child so it draws over everything, and hand `progress` either a `() -> float`
17returning 0..1 or any object with a `.progress` attribute, such as an asset
18`BatchHandle`. `set_progress(fraction, caption)` sets the line under the bar.
19The splash stays up until loading reaches 1.0 and its `min_display_time` has
20passed; with `skippable=True` any key, click or tap after loading ends the hold
21early. When it has faded off the scene it emits `finished`, which is where the
22game tears it down.
23
24Here each press of L, or a click or tap, loads the next level behind a splash
25that fakes a 2.5 second load off `tree.now`. The animated background shows the
26splash covering a running scene and fading back onto it in a new colour.
27"""
28
29import math
30
31from simvx.core import Anchor, Colour, Control, Key, Label, Pointer, SplashScreen, on_input
32from simvx.graphics import App
33
34LOAD_TIME = 2.5 # seconds the pretend level load takes
35
36
37class SplashDemo(Control):
38 dynamic = True
39 input_context = {"load": [Key.L, Pointer.PRIMARY]}
40
41 def on_ready(self):
42 self.anchor = Anchor.FULL_RECT
43 self.level = 1
44 self.splash = None
45 self.hint = self.add_child(
46 Label("Press L or click to load the next level", font_size=18, anchor=Anchor.TOP_LEFT, inset=24)
47 )
48
49 @on_input("load")
50 def load_next_level(self, _event):
51 if self.splash is not None:
52 return
53 started = self.tree.now
54 self.splash = self.add_child(
55 SplashScreen(progress=lambda: min(1.0, (self.tree.now - started) / LOAD_TIME), skippable=True)
56 )
57 self.splash.set_progress(0.0, f"Loading level {self.level + 1}")
58 self.splash.finished.connect(self.level_loaded)
59
60 def level_loaded(self):
61 self.level += 1
62 self.hint.text = f"Level {self.level} loaded. Press L or click to load another."
63 self.splash.destroy()
64 self.splash = None
65
66 def on_draw(self, renderer):
67 w, h = self.viewport_size
68 t = self.tree.now
69 renderer.rect((0, 0), (w, h), fill=Colour.hex("#173042" if self.level % 2 else "#2b1a38"))
70 hue = (self.level * 0.13) % 1.0
71 for i in range(8):
72 a = t * 0.8 + i * math.tau / 8
73 x = w / 2 + math.cos(a) * (120 + 40 * math.sin(t + i))
74 y = h / 2 + math.sin(a) * (90 + 30 * math.cos(t + i))
75 renderer.circle((x, y), 14 + 6 * math.sin(t * 2 + i), fill=(0.2 + hue * 0.5, 0.8, 0.7, 0.85))
76
77
78if __name__ == "__main__":
79 App(title="SimVX Splash Screen", width=800, height=600).run(SplashDemo())