fix(speed): 배속 관련 버그 수정

- 광고 후 배속 적용 안됨: isShowingAd 플래그로 lifecycle reload 방지
- 배속 종료 후 복귀 안됨: setSpeed(_savedSpeedMultiplier) 추가
- 복귀 상자 장비 장착 안됨: _loop?.replaceState() 추가
- 세이브 로드 시 1배속 고정: 명예의 전당 해금 시 최소 2배속 보장
This commit is contained in:
JiWoong Sul
2026-01-19 19:39:32 +09:00
parent 03ff9c1ce8
commit d90543dd86
2 changed files with 27 additions and 3 deletions

View File

@@ -289,11 +289,14 @@ class _GamePlayScreenState extends State<GamePlayScreen>
} }
// 모바일: 앱이 포그라운드로 돌아올 때 전체 재로드 // 모바일: 앱이 포그라운드로 돌아올 때 전체 재로드
// (광고 표시 중에는 reload 건너뛰기 - 배속 부스트 등 상태 유지)
if (appState == AppLifecycleState.resumed && isMobile) { if (appState == AppLifecycleState.resumed && isMobile) {
_audioController.resumeAll(); _audioController.resumeAll();
if (!widget.controller.isShowingAd) {
_reloadGameScreen(); _reloadGameScreen();
} }
} }
}
/// 모바일 재진입 시 전체 화면 재로드 /// 모바일 재진입 시 전체 화면 재로드
Future<void> _reloadGameScreen() async { Future<void> _reloadGameScreen() async {
@@ -659,6 +662,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
speedBoostEndMs: widget.controller.monetization.speedBoostEndMs, speedBoostEndMs: widget.controller.monetization.speedBoostEndMs,
isPaidUser: widget.controller.monetization.isPaidUser, isPaidUser: widget.controller.monetization.isPaidUser,
onSpeedBoostActivate: _handleSpeedBoost, onSpeedBoostActivate: _handleSpeedBoost,
isSpeedBoostActive: widget.controller.isSpeedBoostActive,
adSpeedMultiplier: widget.controller.adSpeedMultiplier, adSpeedMultiplier: widget.controller.adSpeedMultiplier,
has2xUnlocked: widget.controller.has2xUnlocked, has2xUnlocked: widget.controller.has2xUnlocked,
), ),

View File

@@ -66,6 +66,9 @@ class GameSessionController extends ChangeNotifier {
int _speedBoostRemainingSeconds = 0; int _speedBoostRemainingSeconds = 0;
static const int _speedBoostDuration = 300; // 5분 static const int _speedBoostDuration = 300; // 5분
// 광고 표시 중 플래그 (lifecycle reload 방지용)
bool _isShowingAd = false;
/// 광고 배속 배율 (릴리즈: 5x, 디버그빌드+디버그모드: 20x) /// 광고 배속 배율 (릴리즈: 5x, 디버그빌드+디버그모드: 20x)
int get _speedBoostMultiplier => (kDebugMode && _cheatsEnabled) ? 20 : 5; int get _speedBoostMultiplier => (kDebugMode && _cheatsEnabled) ? 20 : 5;
@@ -153,8 +156,16 @@ class GameSessionController extends ChangeNotifier {
// 명예의 전당 체크 → 가용 배속 결정 // 명예의 전당 체크 → 가용 배속 결정
final availableSpeeds = await _getAvailableSpeeds(); final availableSpeeds = await _getAvailableSpeeds();
// 새 게임이면 1배속, 재개/부활이면 기존 배속 유지 // 명예의 전당 해금 시 기본 2배속, 아니면 1배속
final initialSpeed = isNewGame ? 1 : previousSpeed; 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( _loop = ProgressLoop(
initialState: state, initialState: state,
@@ -593,6 +604,9 @@ class GameSessionController extends ChangeNotifier {
/// 속도 부스트 활성화 여부 /// 속도 부스트 활성화 여부
bool get isSpeedBoostActive => _isSpeedBoostActive; bool get isSpeedBoostActive => _isSpeedBoostActive;
/// 광고 표시 중 여부 (lifecycle reload 방지용)
bool get isShowingAd => _isShowingAd;
/// 속도 부스트 남은 시간 (초) /// 속도 부스트 남은 시간 (초)
int get speedBoostRemainingSeconds => _speedBoostRemainingSeconds; int get speedBoostRemainingSeconds => _speedBoostRemainingSeconds;
@@ -626,6 +640,8 @@ class GameSessionController extends ChangeNotifier {
// 무료 유저는 인터스티셜 광고 필요 // 무료 유저는 인터스티셜 광고 필요
bool activated = false; bool activated = false;
_isShowingAd = true; // 광고 표시 시작 (lifecycle reload 방지)
final adResult = await AdService.instance.showInterstitialAd( final adResult = await AdService.instance.showInterstitialAd(
adType: AdType.interstitialSpeed, adType: AdType.interstitialSpeed,
onComplete: () { onComplete: () {
@@ -634,6 +650,8 @@ class GameSessionController extends ChangeNotifier {
}, },
); );
_isShowingAd = false; // 광고 표시 종료
if (adResult == AdResult.completed || adResult == AdResult.debugSkipped) { if (adResult == AdResult.completed || adResult == AdResult.debugSkipped) {
debugPrint('[GameSession] Speed boost activated (free user with ad)'); debugPrint('[GameSession] Speed boost activated (free user with ad)');
return activated; return activated;
@@ -690,6 +708,7 @@ class GameSessionController extends ChangeNotifier {
if (_loop != null) { if (_loop != null) {
_getAvailableSpeeds().then((speeds) { _getAvailableSpeeds().then((speeds) {
_loop!.updateAvailableSpeeds(speeds); _loop!.updateAvailableSpeeds(speeds);
_loop!.setSpeed(_savedSpeedMultiplier);
}); });
} }
@@ -825,6 +844,7 @@ class GameSessionController extends ChangeNotifier {
} }
_state = updatedState; _state = updatedState;
_loop?.replaceState(updatedState); // ProgressLoop 상태도 업데이트
// 저장 // 저장
unawaited(saveManager.saveState( unawaited(saveManager.saveState(