feat(game): 게임 클리어 시 VictoryOverlay 추가
- VictoryOverlay 위젯 신규 생성 - GameSessionController에 isComplete 상태 추가 - 레벨 100 도달 시 승리 오버레이 표시 - 승리 후 명예의 전당 화면으로 이동
This commit is contained in:
@@ -12,18 +12,16 @@ import 'package:asciineverdie/src/core/animation/ascii_animation_type.dart';
|
||||
import 'package:asciineverdie/src/core/engine/story_service.dart';
|
||||
import 'package:asciineverdie/src/core/model/combat_event.dart';
|
||||
import 'package:asciineverdie/src/core/l10n/game_data_l10n.dart';
|
||||
import 'package:asciineverdie/src/core/model/combat_stats.dart';
|
||||
import 'package:asciineverdie/src/core/model/game_state.dart';
|
||||
import 'package:asciineverdie/src/core/model/hall_of_fame.dart';
|
||||
import 'package:asciineverdie/src/core/model/skill.dart';
|
||||
import 'package:asciineverdie/src/core/notification/notification_service.dart';
|
||||
import 'package:asciineverdie/src/core/storage/hall_of_fame_storage.dart';
|
||||
import 'package:asciineverdie/src/core/util/pq_logic.dart' as pq_logic;
|
||||
import 'package:asciineverdie/src/features/game/game_session_controller.dart';
|
||||
import 'package:asciineverdie/src/features/hall_of_fame/hall_of_fame_screen.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/cinematic_view.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/combat_log.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/death_overlay.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/victory_overlay.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/hp_mp_bar.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/notification_overlay.dart';
|
||||
import 'package:asciineverdie/src/features/game/widgets/stats_panel.dart';
|
||||
@@ -138,14 +136,9 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
if (newAct != _lastAct && !_showingCinematic) {
|
||||
_lastAct = newAct;
|
||||
|
||||
// Phase 10: 엔딩 도달 시 클리어 처리 (시네마틱 대신 클리어 다이얼로그)
|
||||
// 다음 프레임에서 실행 (리스너 콜백 중 showDialog 문제 방지)
|
||||
if (newAct == StoryAct.ending && state.traits.level >= 100) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) _handleGameClear(state);
|
||||
});
|
||||
} else {
|
||||
// 일반 Act 전환 시 시네마틱 표시
|
||||
// 엔딩은 controller.isComplete 상태에서 VictoryOverlay로 처리
|
||||
// 일반 Act 전환 시에만 시네마틱 표시
|
||||
if (newAct != StoryAct.ending) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) _showCinematicForAct(newAct);
|
||||
});
|
||||
@@ -419,49 +412,13 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
_showingCinematic = false;
|
||||
}
|
||||
|
||||
/// Phase 10: 게임 클리어 처리 (Handle Game Clear)
|
||||
Future<void> _handleGameClear(GameState state) async {
|
||||
// 게임 일시 정지
|
||||
await widget.controller.pause(saveOnStop: true);
|
||||
|
||||
// 최종 전투 스탯 계산
|
||||
final combatStats = CombatStats.fromStats(
|
||||
stats: state.stats,
|
||||
equipment: state.equipment,
|
||||
level: state.traits.level,
|
||||
/// VictoryOverlay 완료 후 명예의 전당 화면으로 이동
|
||||
void _handleVictoryComplete() {
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const HallOfFameScreen(),
|
||||
),
|
||||
);
|
||||
|
||||
// 명예의 전당 엔트리 생성
|
||||
final entry = HallOfFameEntry.fromGameState(
|
||||
state: state,
|
||||
totalDeaths: state.progress.deathCount,
|
||||
monstersKilled: state.progress.monstersKilled,
|
||||
combatStats: combatStats,
|
||||
);
|
||||
|
||||
// 명예의 전당에 저장
|
||||
final storage = HallOfFameStorage();
|
||||
await storage.addEntry(entry);
|
||||
|
||||
// 클리어 다이얼로그 표시
|
||||
if (mounted) {
|
||||
await showGameClearDialog(
|
||||
context,
|
||||
entry: entry,
|
||||
onNewGame: () {
|
||||
// 프론트 화면으로 돌아가기
|
||||
Navigator.of(context).popUntil((route) => route.isFirst);
|
||||
},
|
||||
onViewHallOfFame: () {
|
||||
// 명예의 전당 화면으로 이동
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (context) => const HallOfFameScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _resetSpecialAnimationAfterFrame() {
|
||||
@@ -857,6 +814,15 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
traits: state.traits,
|
||||
onResurrect: _handleResurrect,
|
||||
),
|
||||
// 승리 오버레이 (게임 클리어)
|
||||
if (widget.controller.isComplete)
|
||||
VictoryOverlay(
|
||||
traits: state.traits,
|
||||
stats: state.stats,
|
||||
progress: state.progress,
|
||||
elapsedMs: state.skillSystem.elapsedMs,
|
||||
onComplete: _handleVictoryComplete,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -990,6 +956,15 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
traits: state.traits,
|
||||
onResurrect: _handleResurrect,
|
||||
),
|
||||
// 승리 오버레이 (게임 클리어)
|
||||
if (widget.controller.isComplete)
|
||||
VictoryOverlay(
|
||||
traits: state.traits,
|
||||
stats: state.stats,
|
||||
progress: state.progress,
|
||||
elapsedMs: state.skillSystem.elapsedMs,
|
||||
onComplete: _handleVictoryComplete,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user