From a8d818917fef8f19877253eeb306e1a003d7d648 Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Tue, 30 Dec 2025 17:15:40 +0900 Subject: [PATCH] =?UTF-8?q?feat(mobile):=20=EC=95=B1=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=ED=94=84=EC=82=AC=EC=9D=B4=ED=81=B4=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EA=B2=8C=EC=9E=84/=EC=98=A4=EB=94=94=EC=98=A4=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EA=B4=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _playInitialBgm() 추가: 게임 로드 시 전투 상태에 맞는 BGM 재생 - 백그라운드 진입 시 게임 일시정지 및 BGM 정지 (모바일) - 포그라운드 복귀 시 세이브에서 재로드 및 화면 재생성 - didChangeAppLifecycleState 개선으로 모바일 UX 향상 --- lib/src/features/game/game_play_screen.dart | 85 ++++++++++++++++++--- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/lib/src/features/game/game_play_screen.dart b/lib/src/features/game/game_play_screen.dart index 7a2670f..f763683 100644 --- a/lib/src/features/game/game_play_screen.dart +++ b/lib/src/features/game/game_play_screen.dart @@ -221,6 +221,31 @@ class _GamePlayScreenState extends State _lastProcessedEventCount = events.length; } + /// 초기 BGM 재생 (게임 시작/로드 시) + void _playInitialBgm(GameState state) { + final audio = widget.audioService; + if (audio == null) return; + + final combat = state.progress.currentCombat; + final isInCombat = combat != null && combat.isActive; + + if (isInCombat) { + // 전투 중: 보스 여부에 따라 BGM 선택 + final monsterLevel = state.progress.currentTask.monsterLevel ?? 0; + final playerLevel = state.traits.level; + final isBoss = monsterLevel >= playerLevel + 5; + + if (isBoss) { + audio.playBgm('boss'); + } else { + audio.playBgm('battle'); + } + } else { + // 비전투: 마을 BGM + audio.playBgm('town'); + } + } + /// 전투 상태에 따른 BGM 전환 void _updateBgmForCombatState(GameState state) { final audio = widget.audioService; @@ -450,17 +475,20 @@ class _GamePlayScreenState extends State _lastPlotStageCount = state.progress.plotStageCount; _lastAct = getActForLevel(state.traits.level); - // 초기 전투 상태 확인 + // 초기 전투 상태 확인 및 BGM 설정 final combat = state.progress.currentCombat; _wasInCombat = combat != null && combat.isActive; + + // 초기 BGM 재생 (전투 상태에 따라) + _playInitialBgm(state); + } else { + // 상태가 없으면 기본 마을 BGM + widget.audioService?.playBgm('town'); } // 누적 통계 로드 widget.controller.loadCumulativeStats(); - // 초기 BGM 재생 (마을 테마) - widget.audioService?.playBgm('town'); - // 오디오 볼륨 초기화 _initAudioVolumes(); } @@ -485,15 +513,52 @@ class _GamePlayScreenState extends State } @override - void didChangeAppLifecycleState(AppLifecycleState state) { - super.didChangeAppLifecycleState(state); + void didChangeAppLifecycleState(AppLifecycleState appState) { + super.didChangeAppLifecycleState(appState); - // 앱이 백그라운드로 가거나 비활성화될 때 자동 저장 - if (state == AppLifecycleState.paused || - state == AppLifecycleState.inactive || - state == AppLifecycleState.detached) { + // 모바일 환경 확인 (iOS/Android) + final isMobile = !kIsWeb && + (defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.android); + + // 앱이 백그라운드로 가거나 비활성화될 때 + if (appState == AppLifecycleState.paused || + appState == AppLifecycleState.inactive || + appState == AppLifecycleState.detached) { + // 저장 _saveGameState(); + + // 모바일: 게임 일시정지 + 사운드 정지 + if (isMobile) { + widget.controller.pause(saveOnStop: false); + widget.audioService?.stopBgm(); + } } + + // 모바일: 앱이 포그라운드로 돌아올 때 전체 재로드 + if (appState == AppLifecycleState.resumed && isMobile) { + _reloadGameScreen(); + } + } + + /// 모바일 재진입 시 전체 화면 재로드 + Future _reloadGameScreen() async { + // 세이브 파일에서 다시 로드 + await widget.controller.loadAndStart(cheatsEnabled: widget.controller.cheatsEnabled); + + if (!mounted) return; + + // 화면 재생성 (상태 초기화) + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (_) => GamePlayScreen( + controller: widget.controller, + audioService: widget.audioService, + currentThemeMode: widget.currentThemeMode, + onThemeModeChange: widget.onThemeModeChange, + ), + ), + ); } Future _saveGameState() async {