feat: Enhance intro splash screen with retail warning and dynamic slide management

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-20 12:18:34 +01:00
parent b23c02f716
commit 436f498778
5 changed files with 197 additions and 20 deletions
@@ -9,6 +9,8 @@ enum WolfMenuScreen {
difficultySelect,
}
enum WolfIntroSlide { retailWarning, pg13, title }
enum _WolfIntroPhase { fadeIn, hold, fadeOut }
enum WolfMenuMainAction {
@@ -61,7 +63,7 @@ bool _isWiredMainMenuAction(WolfMenuMainAction action) {
class MenuManager {
static const int transitionDurationMs = 280;
static const int introFadeDurationMs = 280;
static const int _introSlideCount = 2;
static const int _introRetailBackgroundRgb = 0xA00000;
static const int _introPg13BackgroundRgb = 0x33A2E8;
static const int _introTitleBackgroundRgb = 0x000000;
@@ -74,6 +76,10 @@ class MenuManager {
int _introElapsedMs = 0;
_WolfIntroPhase _introPhase = _WolfIntroPhase.fadeIn;
bool _introAdvanceRequested = false;
List<WolfIntroSlide> _introSlides = <WolfIntroSlide>[
WolfIntroSlide.pg13,
WolfIntroSlide.title,
];
int _selectedMainIndex = 0;
int _selectedGameIndex = 0;
@@ -93,10 +99,31 @@ class MenuManager {
bool get isIntroSplashActive => _activeMenu == WolfMenuScreen.introSplash;
bool get isIntroPg13Slide => _introSlideIndex == 0;
WolfIntroSlide get currentIntroSlide {
if (_introSlides.isEmpty) {
return WolfIntroSlide.title;
}
final int index = _introSlideIndex.clamp(0, _introSlides.length - 1);
return _introSlides[index];
}
int get introBackgroundRgb =>
isIntroPg13Slide ? _introPg13BackgroundRgb : _introTitleBackgroundRgb;
bool get isIntroRetailWarningSlide =>
currentIntroSlide == WolfIntroSlide.retailWarning;
bool get isIntroPg13Slide => currentIntroSlide == WolfIntroSlide.pg13;
bool get isIntroTitleSlide => currentIntroSlide == WolfIntroSlide.title;
int get introBackgroundRgb {
switch (currentIntroSlide) {
case WolfIntroSlide.retailWarning:
return _introRetailBackgroundRgb;
case WolfIntroSlide.pg13:
return _introPg13BackgroundRgb;
case WolfIntroSlide.title:
return _introTitleBackgroundRgb;
}
}
double get introOverlayAlpha {
if (!isIntroSplashActive) {
@@ -189,6 +216,7 @@ class MenuManager {
int initialEpisodeIndex = 0,
Difficulty? initialDifficulty,
bool hasResumableGame = false,
bool initialGameIsRetail = false,
}) {
_gameCount = gameCount;
_showResumeOption = hasResumableGame;
@@ -206,8 +234,12 @@ class MenuManager {
_introElapsedMs = 0;
_introPhase = _WolfIntroPhase.fadeIn;
_introSlideIndex = 0;
_introSlides = <WolfIntroSlide>[
WolfIntroSlide.pg13,
WolfIntroSlide.title,
];
} else {
_startIntroSequence();
_startIntroSequence(includeRetailWarning: initialGameIsRetail);
}
_transitionTarget = null;
_transitionElapsedMs = 0;
@@ -218,12 +250,13 @@ class MenuManager {
/// Starts the intro splash sequence and lands on [landingMenu] when done.
void beginIntroSplash({
WolfMenuScreen landingMenu = WolfMenuScreen.mainMenu,
bool includeRetailWarning = false,
}) {
_introLandingMenu = landingMenu;
_transitionTarget = null;
_transitionElapsedMs = 0;
_transitionSwappedMenu = false;
_startIntroSequence();
_startIntroSequence(includeRetailWarning: includeRetailWarning);
_resetEdgeState();
}
@@ -312,8 +345,15 @@ class MenuManager {
_consumeEdgeState(input);
}
void _startIntroSequence() {
void _startIntroSequence({required bool includeRetailWarning}) {
_activeMenu = WolfMenuScreen.introSplash;
_introSlides = includeRetailWarning
? <WolfIntroSlide>[
WolfIntroSlide.retailWarning,
WolfIntroSlide.pg13,
WolfIntroSlide.title,
]
: <WolfIntroSlide>[WolfIntroSlide.pg13, WolfIntroSlide.title];
_introSlideIndex = 0;
_introElapsedMs = 0;
_introPhase = _WolfIntroPhase.fadeIn;
@@ -356,7 +396,7 @@ class MenuManager {
}
void _advanceIntroSlide() {
if (_introSlideIndex < _introSlideCount - 1) {
if (_introSlideIndex < _introSlides.length - 1) {
_introSlideIndex += 1;
_introElapsedMs = 0;
_introPhase = _WolfIntroPhase.fadeIn;