diff --git a/lib/src/features/game/game_play_screen.dart b/lib/src/features/game/game_play_screen.dart index aa7a0f7..890112e 100644 --- a/lib/src/features/game/game_play_screen.dart +++ b/lib/src/features/game/game_play_screen.dart @@ -289,9 +289,12 @@ class _GamePlayScreenState extends State } // 모바일: 앱이 포그라운드로 돌아올 때 전체 재로드 + // (광고 표시 중에는 reload 건너뛰기 - 배속 부스트 등 상태 유지) if (appState == AppLifecycleState.resumed && isMobile) { _audioController.resumeAll(); - _reloadGameScreen(); + if (!widget.controller.isShowingAd) { + _reloadGameScreen(); + } } } @@ -659,6 +662,7 @@ class _GamePlayScreenState extends State speedBoostEndMs: widget.controller.monetization.speedBoostEndMs, isPaidUser: widget.controller.monetization.isPaidUser, onSpeedBoostActivate: _handleSpeedBoost, + isSpeedBoostActive: widget.controller.isSpeedBoostActive, adSpeedMultiplier: widget.controller.adSpeedMultiplier, has2xUnlocked: widget.controller.has2xUnlocked, ), diff --git a/lib/src/features/game/game_session_controller.dart b/lib/src/features/game/game_session_controller.dart index f7a2fcf..d0e8d51 100644 --- a/lib/src/features/game/game_session_controller.dart +++ b/lib/src/features/game/game_session_controller.dart @@ -66,6 +66,9 @@ class GameSessionController extends ChangeNotifier { int _speedBoostRemainingSeconds = 0; static const int _speedBoostDuration = 300; // 5분 + // 광고 표시 중 플래그 (lifecycle reload 방지용) + bool _isShowingAd = false; + /// 광고 배속 배율 (릴리즈: 5x, 디버그빌드+디버그모드: 20x) int get _speedBoostMultiplier => (kDebugMode && _cheatsEnabled) ? 20 : 5; @@ -153,8 +156,16 @@ class GameSessionController extends ChangeNotifier { // 명예의 전당 체크 → 가용 배속 결정 final availableSpeeds = await _getAvailableSpeeds(); - // 새 게임이면 1배속, 재개/부활이면 기존 배속 유지 - final initialSpeed = isNewGame ? 1 : previousSpeed; + // 명예의 전당 해금 시 기본 2배속, 아니면 1배속 + final hasHallOfFame = availableSpeeds.contains(2); + // 새 게임이면 기본 배속, 세이브 로드 시 명예의 전당 해금 시 최소 2배속 보장 + final int initialSpeed; + if (isNewGame) { + initialSpeed = hasHallOfFame ? 2 : 1; + } else { + // 세이브 로드: 명예의 전당 해금 시 최소 2배속 + initialSpeed = (hasHallOfFame && previousSpeed < 2) ? 2 : previousSpeed; + } _loop = ProgressLoop( initialState: state, @@ -593,6 +604,9 @@ class GameSessionController extends ChangeNotifier { /// 속도 부스트 활성화 여부 bool get isSpeedBoostActive => _isSpeedBoostActive; + /// 광고 표시 중 여부 (lifecycle reload 방지용) + bool get isShowingAd => _isShowingAd; + /// 속도 부스트 남은 시간 (초) int get speedBoostRemainingSeconds => _speedBoostRemainingSeconds; @@ -626,6 +640,8 @@ class GameSessionController extends ChangeNotifier { // 무료 유저는 인터스티셜 광고 필요 bool activated = false; + _isShowingAd = true; // 광고 표시 시작 (lifecycle reload 방지) + final adResult = await AdService.instance.showInterstitialAd( adType: AdType.interstitialSpeed, onComplete: () { @@ -634,6 +650,8 @@ class GameSessionController extends ChangeNotifier { }, ); + _isShowingAd = false; // 광고 표시 종료 + if (adResult == AdResult.completed || adResult == AdResult.debugSkipped) { debugPrint('[GameSession] Speed boost activated (free user with ad)'); return activated; @@ -690,6 +708,7 @@ class GameSessionController extends ChangeNotifier { if (_loop != null) { _getAvailableSpeeds().then((speeds) { _loop!.updateAvailableSpeeds(speeds); + _loop!.setSpeed(_savedSpeedMultiplier); }); } @@ -825,6 +844,7 @@ class GameSessionController extends ChangeNotifier { } _state = updatedState; + _loop?.replaceState(updatedState); // ProgressLoop 상태도 업데이트 // 저장 unawaited(saveManager.saveState(