feat(engine): skip splash on subsequent launches
The 1.6 s brand beat is delightful on first launch and tedious on
every subsequent one. spawn_splash now reads SettingsResource and
returns early when first_run_complete is true — the player has
already seen the splash at least once and the onboarding flow that
follows it, so dropping straight into gameplay is the right move.
Reuses the existing first_run_complete signal rather than introducing
a separate splash_seen field; the two states ("I've been here") line
up naturally and avoid carrying a one-shot flag forever.
The first run, a save reset (settings.json deleted), or a headless
test fixture that doesn't register SettingsResource all still see the
full splash — Option<Res<SettingsResource>> defaults to "show" when
absent, so the existing test fixture observes the same spawn it
always did.
Two new tests pin the split: splash_skipped_when_first_run_complete
asserts no SplashRoot spawns when settings say so, and
splash_still_shows_when_first_run_incomplete asserts the first-run
path is unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,7 @@ use bevy::input::touch::Touches;
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::font_plugin::FontResource;
|
||||
use crate::settings_plugin::SettingsResource;
|
||||
use crate::ui_theme::{
|
||||
ACCENT_PRIMARY, BG_BASE, MOTION_SPLASH_FADE_SECS, MOTION_SPLASH_TOTAL_SECS, TEXT_SECONDARY,
|
||||
TYPE_CAPTION, TYPE_DISPLAY, VAL_SPACE_2, Z_SPLASH,
|
||||
@@ -108,7 +109,25 @@ struct SplashSubtitle;
|
||||
/// at full alpha (the first `advance_splash` tick will overwrite the
|
||||
/// alpha based on age), centres a "Solitaire Quest" title in
|
||||
/// [`ACCENT_PRIMARY`], and pins a small build-version line below.
|
||||
fn spawn_splash(mut commands: Commands, font_res: Option<Res<FontResource>>) {
|
||||
///
|
||||
/// **Skipped on subsequent launches.** If `SettingsResource` reports
|
||||
/// `first_run_complete == true`, the player has already seen the brand
|
||||
/// beat at least once and we go straight to gameplay — having to wait
|
||||
/// 1.6 s on every launch wears thin fast. The splash still shows on
|
||||
/// first run, after a save reset (settings.json deleted), and under
|
||||
/// `MinimalPlugins` (no `SettingsResource` registered) so the test
|
||||
/// fixture observes the same spawn it always did.
|
||||
fn spawn_splash(
|
||||
mut commands: Commands,
|
||||
font_res: Option<Res<FontResource>>,
|
||||
settings: Option<Res<SettingsResource>>,
|
||||
) {
|
||||
if let Some(settings) = settings.as_deref()
|
||||
&& settings.0.first_run_complete
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let font_handle = font_res.map(|f| f.0.clone()).unwrap_or_default();
|
||||
let title_font = TextFont {
|
||||
font: font_handle.clone(),
|
||||
@@ -371,6 +390,47 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn splash_skipped_when_first_run_complete() {
|
||||
use solitaire_data::Settings;
|
||||
let mut app = App::new();
|
||||
app.add_plugins(MinimalPlugins).add_plugins(SplashPlugin);
|
||||
app.init_resource::<ButtonInput<KeyCode>>();
|
||||
app.init_resource::<ButtonInput<MouseButton>>();
|
||||
// Insert a SettingsResource that says "I've been here before"
|
||||
// before any Startup system runs. spawn_splash should observe
|
||||
// first_run_complete and decline to spawn the overlay.
|
||||
app.insert_resource(SettingsResource(Settings {
|
||||
first_run_complete: true,
|
||||
..Settings::default()
|
||||
}));
|
||||
app.update();
|
||||
assert_eq!(
|
||||
count_splash_roots(&mut app),
|
||||
0,
|
||||
"SplashRoot must NOT spawn on subsequent launches"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn splash_still_shows_when_first_run_incomplete() {
|
||||
use solitaire_data::Settings;
|
||||
let mut app = App::new();
|
||||
app.add_plugins(MinimalPlugins).add_plugins(SplashPlugin);
|
||||
app.init_resource::<ButtonInput<KeyCode>>();
|
||||
app.init_resource::<ButtonInput<MouseButton>>();
|
||||
app.insert_resource(SettingsResource(Settings {
|
||||
first_run_complete: false,
|
||||
..Settings::default()
|
||||
}));
|
||||
app.update();
|
||||
assert_eq!(
|
||||
count_splash_roots(&mut app),
|
||||
1,
|
||||
"SplashRoot must spawn for first-run players (first_run_complete = false)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn splash_despawns_after_total_duration() {
|
||||
let mut app = headless_app();
|
||||
|
||||
Reference in New Issue
Block a user