Splash Screen

the branded boot splash and a reusable loading screen.

▶ Run in browser

Tags: 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())