feat(game): 게임 시스템 전면 개편 및 다국어 지원 확장
## 스킬 시스템 개선 - skill_data.dart: 스킬 데이터 구조 전면 개편 (+1176 라인) - skill_service.dart: 스킬 발동 로직 확장 및 버프 시스템 연동 - skill.dart: 스킬 모델 개선, 쿨다운/효과 타입 추가 ## Canvas 애니메이션 리팩토링 - battle_composer.dart 삭제 (레거시 위젯 기반 렌더러) - monster_colors.dart 삭제 (AsciiCell 색상 시스템으로 통합) - canvas_battle_composer.dart: z-index 정렬 (몬스터 z=1, 캐릭터 z=2, 이펙트 z=3) - ascii_cell.dart, ascii_layer.dart: 코드 정리 ## UI/UX 개선 - hp_mp_bar.dart: l10n 적용, 몬스터 HP 바 컴팩트화 - death_overlay.dart: 사망 화면 개선 - equipment_stats_panel.dart: 장비 스탯 표시 확장 - active_buff_panel.dart: 버프 패널 개선 - notification_overlay.dart: 알림 시스템 개선 ## 다국어 지원 확장 - game_text_l10n.dart: 게임 텍스트 통합 (+758 라인) - 한국어/일본어/영어/중국어 번역 업데이트 - ARB 파일 동기화 ## 게임 로직 개선 - progress_service.dart: 진행 로직 리팩토링 - combat_calculator.dart: 전투 계산 로직 개선 - stat_calculator.dart: 스탯 계산 시스템 개선 - story_service.dart: 스토리 진행 로직 개선 ## 기타 - theme_preferences.dart 삭제 (미사용) - 테스트 파일 업데이트 - class_data.dart: 클래스 데이터 정리
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/data/game_text_l10n.dart' as l10n;
|
||||
import 'package:askiineverdie/src/core/l10n/game_data_l10n.dart';
|
||||
import 'package:askiineverdie/src/core/model/hall_of_fame.dart';
|
||||
import 'package:askiineverdie/src/core/storage/hall_of_fame_storage.dart';
|
||||
@@ -36,10 +37,7 @@ class _HallOfFameScreenState extends State<HallOfFameScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Hall of Fame'),
|
||||
centerTitle: true,
|
||||
),
|
||||
appBar: AppBar(title: Text(l10n.uiHallOfFame), centerTitle: true),
|
||||
body: _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: _buildContent(),
|
||||
@@ -67,19 +65,13 @@ class _HallOfFameScreenState extends State<HallOfFameScreen> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'No heroes yet',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
l10n.hofNoHeroes,
|
||||
style: TextStyle(fontSize: 20, color: Colors.grey.shade600),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Defeat the Glitch God to enshrine your legend!',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade500,
|
||||
),
|
||||
l10n.hofDefeatGlitchGod,
|
||||
style: TextStyle(fontSize: 14, color: Colors.grey.shade500),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
@@ -106,22 +98,22 @@ class _HallOfFameScreenState extends State<HallOfFameScreen> {
|
||||
topRight: Radius.circular(6),
|
||||
),
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.emoji_events, color: Colors.white),
|
||||
SizedBox(width: 8),
|
||||
const Icon(Icons.emoji_events, color: Colors.white),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'HALL OF FAME',
|
||||
style: TextStyle(
|
||||
l10n.uiHallOfFame.toUpperCase(),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 2,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Icon(Icons.emoji_events, color: Colors.white),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.emoji_events, color: Colors.white),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -132,10 +124,7 @@ class _HallOfFameScreenState extends State<HallOfFameScreen> {
|
||||
itemCount: hallOfFame.entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
final entry = hallOfFame.entries[index];
|
||||
return _HallOfFameEntryCard(
|
||||
entry: entry,
|
||||
rank: index + 1,
|
||||
);
|
||||
return _HallOfFameEntryCard(entry: entry, rank: index + 1);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -147,10 +136,7 @@ class _HallOfFameScreenState extends State<HallOfFameScreen> {
|
||||
|
||||
/// 명예의 전당 엔트리 카드
|
||||
class _HallOfFameEntryCard extends StatelessWidget {
|
||||
const _HallOfFameEntryCard({
|
||||
required this.entry,
|
||||
required this.rank,
|
||||
});
|
||||
const _HallOfFameEntryCard({required this.entry, required this.rank});
|
||||
|
||||
final HallOfFameEntry entry;
|
||||
final int rank;
|
||||
@@ -217,7 +203,7 @@ class _HallOfFameEntryCard extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
'Lv.${entry.level}',
|
||||
l10n.uiLevel(entry.level),
|
||||
style: TextStyle(
|
||||
color: Colors.blue.shade800,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -232,10 +218,7 @@ class _HallOfFameEntryCard extends StatelessWidget {
|
||||
Text(
|
||||
'${GameDataL10n.getRaceName(context, entry.race)} '
|
||||
'${GameDataL10n.getKlassName(context, entry.klass)}',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey.shade700,
|
||||
),
|
||||
style: TextStyle(fontSize: 13, color: Colors.grey.shade700),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
// 통계
|
||||
@@ -267,14 +250,15 @@ class _HallOfFameEntryCard extends StatelessWidget {
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Icon(Icons.calendar_today, size: 14, color: Colors.grey.shade500),
|
||||
Icon(
|
||||
Icons.calendar_today,
|
||||
size: 14,
|
||||
color: Colors.grey.shade500,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
entry.formattedClearedDate,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
style: TextStyle(fontSize: 11, color: Colors.grey.shade600),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -362,22 +346,22 @@ class _GameClearDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Row(
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.emoji_events, color: Colors.amber, size: 32),
|
||||
SizedBox(width: 8),
|
||||
Text('VICTORY!'),
|
||||
SizedBox(width: 8),
|
||||
Icon(Icons.emoji_events, color: Colors.amber, size: 32),
|
||||
const Icon(Icons.emoji_events, color: Colors.amber, size: 32),
|
||||
const SizedBox(width: 8),
|
||||
Text(l10n.hofVictory),
|
||||
const SizedBox(width: 8),
|
||||
const Icon(Icons.emoji_events, color: Colors.amber, size: 32),
|
||||
],
|
||||
),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'You have defeated the Glitch God!',
|
||||
style: TextStyle(fontSize: 16),
|
||||
Text(
|
||||
l10n.hofDefeatedGlitchGod,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
@@ -386,14 +370,11 @@ class _GameClearDialog extends StatelessWidget {
|
||||
// 캐릭터 정보
|
||||
Text(
|
||||
'"${entry.characterName}"',
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'${entry.race} ${entry.klass}',
|
||||
'${GameDataL10n.getRaceName(context, entry.race)} ${GameDataL10n.getKlassName(context, entry.klass)}',
|
||||
style: TextStyle(color: Colors.grey.shade600),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
@@ -401,16 +382,16 @@ class _GameClearDialog extends StatelessWidget {
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_buildStat('Level', '${entry.level}'),
|
||||
_buildStat('Time', entry.formattedPlayTime),
|
||||
_buildStat('Deaths', '${entry.totalDeaths}'),
|
||||
_buildStat('Quests', '${entry.questsCompleted}'),
|
||||
_buildStat(l10n.hofLevel, '${entry.level}'),
|
||||
_buildStat(l10n.hofTime, entry.formattedPlayTime),
|
||||
_buildStat(l10n.hofDeaths, '${entry.totalDeaths}'),
|
||||
_buildStat(l10n.hofQuests, '${entry.questsCompleted}'),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
'Your legend has been enshrined in the Hall of Fame!',
|
||||
style: TextStyle(
|
||||
Text(
|
||||
l10n.hofLegendEnshrined,
|
||||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Colors.amber,
|
||||
),
|
||||
@@ -424,14 +405,14 @@ class _GameClearDialog extends StatelessWidget {
|
||||
Navigator.of(context).pop();
|
||||
onViewHallOfFame();
|
||||
},
|
||||
child: const Text('View Hall of Fame'),
|
||||
child: Text(l10n.hofViewHallOfFame),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
onNewGame();
|
||||
},
|
||||
child: const Text('New Game'),
|
||||
child: Text(l10n.hofNewGame),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -442,17 +423,11 @@ class _GameClearDialog extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
value,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
style: TextStyle(fontSize: 11, color: Colors.grey.shade600),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user