feat(animation): 종족별 캐릭터 애니메이션 시스템 추가
- 21개 종족별 고유 ASCII 캐릭터 프레임 데이터 추가 - 각 종족당 5가지 상태 애니메이션: idle, prepare, attack, hit, recover - 종족 특성에 맞는 시각적 차별화 (마법사 ~, 기사 ♦, 언데드 ☠ 등) - 캐릭터 생성 화면 종족 미리보기 위젯 추가 - 프론트 화면 Hero vs Boss 애니메이션 개선 - 게임 플레이 화면 애니메이션 패널 연동 강화
This commit is contained in:
@@ -485,10 +485,24 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
onTap: () async {
|
||||
Navigator.pop(context); // 다이얼로그 닫기
|
||||
// 안전한 언어 변경: 전체 화면 재생성
|
||||
final navigator = Navigator.of(this.context);
|
||||
await widget.controller.pause(saveOnStop: true);
|
||||
game_l10n.setGameLocale(locale);
|
||||
setState(() {});
|
||||
if (mounted) {
|
||||
await widget.controller.resume();
|
||||
navigator.pushReplacement(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => GamePlayScreen(
|
||||
controller: widget.controller,
|
||||
currentThemeMode: widget.currentThemeMode,
|
||||
onThemeModeChange: widget.onThemeModeChange,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -573,6 +587,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
notificationService: _notificationService,
|
||||
specialAnimation: _specialAnimation,
|
||||
onLanguageChange: (locale) async {
|
||||
// navigator 참조를 async gap 전에 저장
|
||||
final navigator = Navigator.of(context);
|
||||
// 1. 현재 상태 저장
|
||||
await widget.controller.pause(saveOnStop: true);
|
||||
// 2. 로케일 변경
|
||||
@@ -580,7 +596,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
// 3. 화면 재생성 (전체 UI 재구성)
|
||||
if (context.mounted) {
|
||||
await widget.controller.resume();
|
||||
Navigator.of(context).pushReplacement(
|
||||
navigator.pushReplacement(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => GamePlayScreen(
|
||||
controller: widget.controller,
|
||||
@@ -689,6 +705,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
monsterLevel: state.progress.currentTask.monsterLevel,
|
||||
latestCombatEvent:
|
||||
state.progress.currentCombat?.recentEvents.lastOrNull,
|
||||
raceId: state.traits.raceId,
|
||||
),
|
||||
|
||||
// 메인 3패널 영역
|
||||
|
||||
@@ -405,6 +405,7 @@ class _MobileCarouselLayoutState extends State<MobileCarouselLayout> {
|
||||
monsterLevel: state.progress.currentTask.monsterLevel,
|
||||
latestCombatEvent:
|
||||
state.progress.currentCombat?.recentEvents.lastOrNull,
|
||||
raceId: state.traits.raceId,
|
||||
),
|
||||
|
||||
// 중앙: 캐로셀 (PageView)
|
||||
|
||||
@@ -45,6 +45,7 @@ class AsciiAnimationCard extends StatefulWidget {
|
||||
this.monsterLevel,
|
||||
this.isPaused = false,
|
||||
this.latestCombatEvent,
|
||||
this.raceId,
|
||||
});
|
||||
|
||||
final TaskType taskType;
|
||||
@@ -75,6 +76,9 @@ class AsciiAnimationCard extends StatefulWidget {
|
||||
/// 최근 전투 이벤트 (애니메이션 동기화용)
|
||||
final CombatEvent? latestCombatEvent;
|
||||
|
||||
/// 종족 ID (Phase 4: 종족별 캐릭터 애니메이션)
|
||||
final String? raceId;
|
||||
|
||||
@override
|
||||
State<AsciiAnimationCard> createState() => _AsciiAnimationCardState();
|
||||
}
|
||||
@@ -168,7 +172,8 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
|
||||
oldWidget.monsterBaseName != widget.monsterBaseName ||
|
||||
oldWidget.weaponName != widget.weaponName ||
|
||||
oldWidget.shieldName != widget.shieldName ||
|
||||
oldWidget.monsterLevel != widget.monsterLevel) {
|
||||
oldWidget.monsterLevel != widget.monsterLevel ||
|
||||
oldWidget.raceId != widget.raceId) {
|
||||
_updateAnimation();
|
||||
}
|
||||
}
|
||||
@@ -391,6 +396,7 @@ class _AsciiAnimationCardState extends State<AsciiAnimationCard> {
|
||||
hasShield: hasShield,
|
||||
monsterCategory: monsterCategory,
|
||||
monsterSize: monsterSize,
|
||||
raceId: widget.raceId,
|
||||
);
|
||||
|
||||
// 환경 타입 추론
|
||||
|
||||
@@ -30,6 +30,7 @@ class EnhancedAnimationPanel extends StatefulWidget {
|
||||
this.characterLevel,
|
||||
this.monsterLevel,
|
||||
this.latestCombatEvent,
|
||||
this.raceId,
|
||||
});
|
||||
|
||||
final ProgressState progress;
|
||||
@@ -46,6 +47,9 @@ class EnhancedAnimationPanel extends StatefulWidget {
|
||||
final int? monsterLevel;
|
||||
final CombatEvent? latestCombatEvent;
|
||||
|
||||
/// 종족 ID (Phase 4: 종족별 캐릭터 애니메이션)
|
||||
final String? raceId;
|
||||
|
||||
@override
|
||||
State<EnhancedAnimationPanel> createState() => _EnhancedAnimationPanelState();
|
||||
}
|
||||
@@ -183,6 +187,7 @@ class _EnhancedAnimationPanelState extends State<EnhancedAnimationPanel>
|
||||
monsterLevel: widget.monsterLevel,
|
||||
isPaused: widget.isPaused,
|
||||
latestCombatEvent: widget.latestCombatEvent,
|
||||
raceId: widget.raceId,
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class TaskProgressPanel extends StatelessWidget {
|
||||
this.characterLevel,
|
||||
this.monsterLevel,
|
||||
this.latestCombatEvent,
|
||||
this.raceId,
|
||||
});
|
||||
|
||||
final ProgressState progress;
|
||||
@@ -45,6 +46,9 @@ class TaskProgressPanel extends StatelessWidget {
|
||||
/// 최근 전투 이벤트 (애니메이션 동기화용, Phase 5)
|
||||
final CombatEvent? latestCombatEvent;
|
||||
|
||||
/// 종족 ID (Phase 4: 종족별 캐릭터 애니메이션)
|
||||
final String? raceId;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
@@ -71,6 +75,7 @@ class TaskProgressPanel extends StatelessWidget {
|
||||
monsterLevel: monsterLevel,
|
||||
isPaused: isPaused,
|
||||
latestCombatEvent: latestCombatEvent,
|
||||
raceId: raceId,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
Reference in New Issue
Block a user