feat(engine): branded splash screen on launch
The window previously snapped straight to a card deal, which read more like a prototype than a finished game. SplashPlugin lays a fullscreen overlay (BG_BASE backdrop, ACCENT_PRIMARY title, version subtitle) on top of the gameplay layer for MOTION_SPLASH_TOTAL_SECS — the board deals behind it so the splash dissolve hands off naturally to the deal animation. Visibility curves through fade-in (300ms), hold (~1s), fade-out (300ms) using a pure splash_alpha helper that gets pinned by a unit test rather than wired to the Bevy clock — Time<Virtual>'s 250ms per-tick clamp makes float-tight alpha assertions around the fade boundary brittle. Any keystroke or mouse-button press jumps the age forward to the fade-out window so the splash dissolves immediately. The dismiss handler is read-only on ButtonInput / Touches, so the same press is still visible to gameplay handlers downstream — pressing Space on the splash both dismisses it and triggers the next-tick stock draw, as verified by dismissal_keypress_is_visible_to_other_systems. Z_SPLASH sits above every other UI rung (Z_TOAST + 100) so the splash owns the viewport for its brief lifetime. The hierarchy test was extended to enforce the new rung's monotonic position. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -282,6 +282,19 @@ pub const MOTION_LOADING_TICK_SECS: f32 = 0.40;
|
||||
/// hover-discoverability budget for help text.
|
||||
pub const MOTION_TOOLTIP_DELAY_SECS: f32 = 0.5;
|
||||
|
||||
/// Total visible duration of the splash screen overlay, in seconds.
|
||||
/// Composed of a fade-in, a hold, and a fade-out — see
|
||||
/// [`MOTION_SPLASH_FADE_SECS`] for the per-edge fade budget. Not run
|
||||
/// through [`scaled_duration`]: the splash is a one-shot brand beat at
|
||||
/// app start, not gameplay motion that should track `AnimSpeed`.
|
||||
pub const MOTION_SPLASH_TOTAL_SECS: f32 = 1.6;
|
||||
|
||||
/// Fade-in and fade-out duration of the splash overlay, in seconds.
|
||||
/// The hold time is `MOTION_SPLASH_TOTAL_SECS - 2 * MOTION_SPLASH_FADE_SECS`.
|
||||
/// Mirroring fade-in and fade-out keeps the curve symmetric so the brand
|
||||
/// beat reads as a single dissolve instead of two separate animations.
|
||||
pub const MOTION_SPLASH_FADE_SECS: f32 = 0.3;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Z-index — tooltip layer
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -292,6 +305,15 @@ pub const MOTION_TOOLTIP_DELAY_SECS: f32 = 0.5;
|
||||
/// celebration and notification layers stay on top.
|
||||
pub const Z_TOOLTIP: i32 = Z_FOCUS_RING + 10;
|
||||
|
||||
/// Z-layer for the launch splash overlay. The splash owns the entire
|
||||
/// viewport for ~1.6 s before fading out, so it sits above every other
|
||||
/// UI rung — including `Z_TOAST` — to guarantee the brand beat is
|
||||
/// never occluded by a stray toast or tooltip. Neither toasts nor the
|
||||
/// win cascade can fire during the splash window in practice (no game
|
||||
/// has run yet, no toast queue has dispatched), but the relative order
|
||||
/// is kept tidy in case a future feature schedules either at startup.
|
||||
pub const Z_SPLASH: i32 = Z_TOAST + 100;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -362,6 +384,7 @@ mod tests {
|
||||
Z_TOOLTIP,
|
||||
Z_WIN_CASCADE,
|
||||
Z_TOAST,
|
||||
Z_SPLASH,
|
||||
];
|
||||
for window in layers.windows(2) {
|
||||
assert!(
|
||||
|
||||
Reference in New Issue
Block a user