refactor(game): 게임 화면 및 위젯 정리

This commit is contained in:
JiWoong Sul
2026-01-12 16:17:20 +09:00
parent 104d23cdfd
commit cbbbbba1a5
13 changed files with 662 additions and 570 deletions

View File

@@ -491,9 +491,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
/// VictoryOverlay 완료 후 명예의 전당 화면으로 이동
void _handleVictoryComplete() {
Navigator.of(context).pushReplacement(
MaterialPageRoute<void>(
builder: (context) => const HallOfFameScreen(),
),
MaterialPageRoute<void>(builder: (context) => const HallOfFameScreen()),
);
}
@@ -570,7 +568,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
super.didChangeAppLifecycleState(appState);
// 모바일 환경 확인 (iOS/Android)
final isMobile = !kIsWeb &&
final isMobile =
!kIsWeb &&
(defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.android);
@@ -815,7 +814,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
setState(() {});
},
// 특수 애니메이션 중에는 일시정지 상태로 표시하지 않음
isPaused: !widget.controller.isRunning && _specialAnimation == null,
isPaused:
!widget.controller.isRunning && _specialAnimation == null,
onPauseToggle: () async {
await widget.controller.togglePause();
setState(() {});
@@ -883,7 +883,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
// 치트 (디버그 모드)
cheatsEnabled: widget.controller.cheatsEnabled,
onCheatTask: () => widget.controller.loop?.cheatCompleteTask(),
onCheatQuest: () => widget.controller.loop?.cheatCompleteQuest(),
onCheatQuest: () =>
widget.controller.loop?.cheatCompleteQuest(),
onCheatPlot: () => widget.controller.loop?.cheatCompletePlot(),
),
// 사망 오버레이
@@ -935,132 +936,137 @@ class _GamePlayScreenState extends State<GamePlayScreen>
autofocus: true,
onKeyEvent: (node, event) => _handleKeyboardShortcut(event, context),
child: Scaffold(
backgroundColor: RetroColors.deepBrown,
appBar: AppBar(
backgroundColor: RetroColors.darkBrown,
title: Text(
L10n.of(context).progressQuestTitle(state.traits.name),
style: const TextStyle(
fontFamily: 'PressStart2P',
fontSize: 12,
color: RetroColors.gold,
),
),
actions: [
// 치트 버튼 (디버그용)
if (widget.controller.cheatsEnabled) ...[
IconButton(
icon: const Text('L+1'),
tooltip: L10n.of(context).levelUp,
onPressed: () => widget.controller.loop?.cheatCompleteTask(),
backgroundColor: RetroColors.deepBrown,
appBar: AppBar(
backgroundColor: RetroColors.darkBrown,
title: Text(
L10n.of(context).progressQuestTitle(state.traits.name),
style: const TextStyle(
fontFamily: 'PressStart2P',
fontSize: 12,
color: RetroColors.gold,
),
IconButton(
icon: const Text('Q!'),
tooltip: L10n.of(context).completeQuest,
onPressed: () => widget.controller.loop?.cheatCompleteQuest(),
),
IconButton(
icon: const Text('P!'),
tooltip: L10n.of(context).completePlot,
onPressed: () => widget.controller.loop?.cheatCompletePlot(),
),
],
// 통계 버튼
IconButton(
icon: const Icon(Icons.bar_chart),
tooltip: game_l10n.uiStatistics,
onPressed: () => _showStatisticsDialog(context),
),
// 도움말 버튼
IconButton(
icon: const Icon(Icons.help_outline),
tooltip: game_l10n.uiHelp,
onPressed: () => HelpDialog.show(context),
),
// 설정 버튼
IconButton(
icon: const Icon(Icons.settings),
tooltip: game_l10n.uiSettings,
onPressed: () => _showSettingsScreen(context),
),
],
),
body: Stack(
children: [
// 메인 게임 UI
Column(
children: [
// 상단: ASCII 애니메이션 + Task Progress (Phase 7: 고정 4색 팔레트)
TaskProgressPanel(
progress: state.progress,
speedMultiplier:
widget.controller.loop?.speedMultiplier ?? 1,
onSpeedCycle: () {
widget.controller.loop?.cycleSpeed();
setState(() {});
},
// 특수 애니메이션 중에는 일시정지 상태로 표시하지 않음
isPaused: !widget.controller.isRunning && _specialAnimation == null,
onPauseToggle: () async {
await widget.controller.togglePause();
setState(() {});
},
specialAnimation: _specialAnimation,
weaponName: state.equipment.weapon,
shieldName: state.equipment.shield,
characterLevel: state.traits.level,
monsterLevel: state.progress.currentTask.monsterLevel,
monsterGrade: state.progress.currentTask.monsterGrade,
latestCombatEvent:
state.progress.currentCombat?.recentEvents.lastOrNull,
raceId: state.traits.raceId,
actions: [
// 치트 버튼 (디버그용)
if (widget.controller.cheatsEnabled) ...[
IconButton(
icon: const Text('L+1'),
tooltip: L10n.of(context).levelUp,
onPressed: () =>
widget.controller.loop?.cheatCompleteTask(),
),
// 메인 3패널 영역
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 좌측 패널: Character Sheet
Expanded(flex: 2, child: _buildCharacterPanel(state)),
// 중앙 패널: Equipment/Inventory
Expanded(flex: 3, child: _buildEquipmentPanel(state)),
// 우측 패널: Plot/Quest
Expanded(flex: 2, child: _buildQuestPanel(state)),
],
),
IconButton(
icon: const Text('Q!'),
tooltip: L10n.of(context).completeQuest,
onPressed: () =>
widget.controller.loop?.cheatCompleteQuest(),
),
IconButton(
icon: const Text('P!'),
tooltip: L10n.of(context).completePlot,
onPressed: () =>
widget.controller.loop?.cheatCompletePlot(),
),
],
),
// 통계 버튼
IconButton(
icon: const Icon(Icons.bar_chart),
tooltip: game_l10n.uiStatistics,
onPressed: () => _showStatisticsDialog(context),
),
// 도움말 버튼
IconButton(
icon: const Icon(Icons.help_outline),
tooltip: game_l10n.uiHelp,
onPressed: () => HelpDialog.show(context),
),
// 설정 버튼
IconButton(
icon: const Icon(Icons.settings),
tooltip: game_l10n.uiSettings,
onPressed: () => _showSettingsScreen(context),
),
],
),
body: Stack(
children: [
// 메인 게임 UI
Column(
children: [
// 상단: ASCII 애니메이션 + Task Progress (Phase 7: 고정 4색 팔레트)
TaskProgressPanel(
progress: state.progress,
speedMultiplier:
widget.controller.loop?.speedMultiplier ?? 1,
onSpeedCycle: () {
widget.controller.loop?.cycleSpeed();
setState(() {});
},
// 특수 애니메이션 중에는 일시정지 상태로 표시하지 않음
isPaused:
!widget.controller.isRunning &&
_specialAnimation == null,
onPauseToggle: () async {
await widget.controller.togglePause();
setState(() {});
},
specialAnimation: _specialAnimation,
weaponName: state.equipment.weapon,
shieldName: state.equipment.shield,
characterLevel: state.traits.level,
monsterLevel: state.progress.currentTask.monsterLevel,
monsterGrade: state.progress.currentTask.monsterGrade,
latestCombatEvent:
state.progress.currentCombat?.recentEvents.lastOrNull,
raceId: state.traits.raceId,
),
// Phase 4: 사망 오버레이 (Death Overlay)
if (state.isDead && state.deathInfo != null)
DeathOverlay(
deathInfo: state.deathInfo!,
traits: state.traits,
onResurrect: _handleResurrect,
isAutoResurrectEnabled: widget.controller.autoResurrect,
onToggleAutoResurrect: () {
widget.controller.setAutoResurrect(
!widget.controller.autoResurrect,
);
},
// 메인 3패널 영역
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 좌측 패널: Character Sheet
Expanded(flex: 2, child: _buildCharacterPanel(state)),
// 중앙 패널: Equipment/Inventory
Expanded(flex: 3, child: _buildEquipmentPanel(state)),
// 우측 패널: Plot/Quest
Expanded(flex: 2, child: _buildQuestPanel(state)),
],
),
),
],
),
// 승리 오버레이 (게임 클리어)
if (widget.controller.isComplete)
VictoryOverlay(
traits: state.traits,
stats: state.stats,
progress: state.progress,
elapsedMs: state.skillSystem.elapsedMs,
onComplete: _handleVictoryComplete,
),
],
// Phase 4: 사망 오버레이 (Death Overlay)
if (state.isDead && state.deathInfo != null)
DeathOverlay(
deathInfo: state.deathInfo!,
traits: state.traits,
onResurrect: _handleResurrect,
isAutoResurrectEnabled: widget.controller.autoResurrect,
onToggleAutoResurrect: () {
widget.controller.setAutoResurrect(
!widget.controller.autoResurrect,
);
},
),
// 승리 오버레이 (게임 클리어)
if (widget.controller.isComplete)
VictoryOverlay(
traits: state.traits,
stats: state.stats,
progress: state.progress,
elapsedMs: state.skillSystem.elapsedMs,
onComplete: _handleVictoryComplete,
),
],
),
),
),
),
),
);
}
@@ -1159,7 +1165,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
state.progress.exp.position,
state.progress.exp.max,
Colors.blue,
tooltip: '${state.progress.exp.position} / ${state.progress.exp.max}',
tooltip:
'${state.progress.exp.position} / ${state.progress.exp.max}',
),
// 스킬 (Skills - SpellBook 기반)
@@ -1286,9 +1293,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
decoration: const BoxDecoration(
color: RetroColors.darkBrown,
border: Border(
bottom: BorderSide(color: RetroColors.gold, width: 2),
),
border: Border(bottom: BorderSide(color: RetroColors.gold, width: 2)),
),
child: Text(
title.toUpperCase(),
@@ -1345,7 +1350,9 @@ class _GamePlayScreenState extends State<GamePlayScreen>
border: Border(
right: index < segmentCount - 1
? BorderSide(
color: RetroColors.panelBorderOuter.withValues(alpha: 0.3),
color: RetroColors.panelBorderOuter.withValues(
alpha: 0.3,
),
width: 1,
)
: BorderSide.none,
@@ -1478,7 +1485,11 @@ class _GamePlayScreenState extends State<GamePlayScreen>
padding: const EdgeInsets.symmetric(vertical: 2),
child: Row(
children: [
const Icon(Icons.monetization_on, size: 10, color: RetroColors.gold),
const Icon(
Icons.monetization_on,
size: 10,
color: RetroColors.gold,
),
const SizedBox(width: 4),
Expanded(
child: Text(
@@ -1568,7 +1579,9 @@ class _GamePlayScreenState extends State<GamePlayScreen>
Icon(
isCompleted
? Icons.check_box
: (isCurrent ? Icons.arrow_right : Icons.check_box_outline_blank),
: (isCurrent
? Icons.arrow_right
: Icons.check_box_outline_blank),
size: 12,
color: isCompleted
? RetroColors.expGreen
@@ -1583,7 +1596,9 @@ class _GamePlayScreenState extends State<GamePlayScreen>
fontSize: 8,
color: isCompleted
? RetroColors.textDisabled
: (isCurrent ? RetroColors.gold : RetroColors.textLight),
: (isCurrent
? RetroColors.gold
: RetroColors.textLight),
decoration: isCompleted
? TextDecoration.lineThrough
: TextDecoration.none,
@@ -1632,14 +1647,14 @@ class _GamePlayScreenState extends State<GamePlayScreen>
isCurrentQuest
? Icons.arrow_right
: (quest.isComplete
? Icons.check_box
: Icons.check_box_outline_blank),
? Icons.check_box
: Icons.check_box_outline_blank),
size: 12,
color: isCurrentQuest
? RetroColors.gold
: (quest.isComplete
? RetroColors.expGreen
: RetroColors.textDisabled),
? RetroColors.expGreen
: RetroColors.textDisabled),
),
const SizedBox(width: 4),
Expanded(
@@ -1651,8 +1666,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
color: isCurrentQuest
? RetroColors.gold
: (quest.isComplete
? RetroColors.textDisabled
: RetroColors.textLight),
? RetroColors.textDisabled
: RetroColors.textLight),
decoration: quest.isComplete
? TextDecoration.lineThrough
: TextDecoration.none,