feat(hall): Phase 10 명예의 전당 시스템 구현

- HallOfFameEntry 모델 및 HallOfFame 컬렉션 추가
- HallOfFameStorage 저장소 (JSON 파일 기반)
- HallOfFameScreen UI (순위별 색상/아이콘)
- 게임 클리어 시 명예의 전당 등록 처리
- FrontScreen에 명예의 전당 버튼 추가
- 클리어 축하 다이얼로그 구현
This commit is contained in:
JiWoong Sul
2025-12-17 18:57:26 +09:00
parent 7c7f3b0d9e
commit 9af5c4dc13
6 changed files with 814 additions and 2 deletions

View File

@@ -6,9 +6,12 @@ import 'package:askiineverdie/src/core/animation/ascii_animation_type.dart';
import 'package:askiineverdie/src/core/engine/story_service.dart';
import 'package:askiineverdie/src/core/l10n/game_data_l10n.dart';
import 'package:askiineverdie/src/core/model/game_state.dart';
import 'package:askiineverdie/src/core/model/hall_of_fame.dart';
import 'package:askiineverdie/src/core/notification/notification_service.dart';
import 'package:askiineverdie/src/core/storage/hall_of_fame_storage.dart';
import 'package:askiineverdie/src/core/util/pq_logic.dart' as pq_logic;
import 'package:askiineverdie/src/features/game/game_session_controller.dart';
import 'package:askiineverdie/src/features/hall_of_fame/hall_of_fame_screen.dart';
import 'package:askiineverdie/src/features/game/widgets/cinematic_view.dart';
import 'package:askiineverdie/src/features/game/widgets/combat_log.dart';
import 'package:askiineverdie/src/features/game/widgets/hp_mp_bar.dart';
@@ -70,6 +73,11 @@ class _GamePlayScreenState extends State<GamePlayScreen>
if (newAct != _lastAct && !_showingCinematic) {
_lastAct = newAct;
_showCinematicForAct(newAct);
// Phase 10: 엔딩 도달 시 클리어 처리
if (newAct == StoryAct.ending && state.traits.level >= 100) {
_handleGameClear(state);
}
}
}
_lastLevel = state.traits.level;
@@ -131,6 +139,43 @@ 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 entry = HallOfFameEntry.fromGameState(
state: state,
totalDeaths: 0, // TODO: 사망 횟수 추적 구현 시 연결
monstersKilled: 0, // TODO: 처치 수 추적 구현 시 연결
);
// 명예의 전당에 저장
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() {
// 다음 프레임에서 리셋 (AsciiAnimationCard가 값을 받은 후)
WidgetsBinding.instance.addPostFrameCallback((_) {