diff --git a/lib/src/core/animation/ascii_animation_type.dart b/lib/src/core/animation/ascii_animation_type.dart index c046250..50c6621 100644 --- a/lib/src/core/animation/ascii_animation_type.dart +++ b/lib/src/core/animation/ascii_animation_type.dart @@ -24,6 +24,33 @@ enum AsciiAnimationType { resurrection, } +// ============================================================================ +// 특수 애니메이션 타이밍 상수 +// ============================================================================ + +/// 특수 애니메이션 프레임 수 +const specialAnimationFrameCounts = { + AsciiAnimationType.levelUp: 5, + AsciiAnimationType.questComplete: 4, + AsciiAnimationType.actComplete: 4, + AsciiAnimationType.resurrection: 5, +}; + +/// 특수 애니메이션 프레임 간격 (밀리초) +const specialAnimationFrameIntervals = { + AsciiAnimationType.levelUp: 300, + AsciiAnimationType.questComplete: 350, + AsciiAnimationType.actComplete: 400, + AsciiAnimationType.resurrection: 600, +}; + +/// 특수 애니메이션 총 지속 시간 (밀리초) +int getSpecialAnimationDuration(AsciiAnimationType type) { + final frames = specialAnimationFrameCounts[type] ?? 1; + final interval = specialAnimationFrameIntervals[type] ?? 200; + return frames * interval; +} + /// TaskType을 AsciiAnimationType으로 변환 AsciiAnimationType taskTypeToAnimation(TaskType taskType) { return switch (taskType) { diff --git a/lib/src/core/animation/canvas/canvas_battle_composer.dart b/lib/src/core/animation/canvas/canvas_battle_composer.dart index 93d5eee..26d605b 100644 --- a/lib/src/core/animation/canvas/canvas_battle_composer.dart +++ b/lib/src/core/animation/canvas/canvas_battle_composer.dart @@ -115,13 +115,13 @@ class CanvasBattleComposer { return AsciiLayer( cells: cells, - zIndex: 1, + zIndex: 2, // 몬스터(z=1) 위에 캐릭터 표시 offsetX: charX, offsetY: charY, ); } - /// 몬스터 레이어 생성 (z=1) + /// 몬스터 레이어 생성 (z=1, 캐릭터보다 뒤) AsciiLayer _createMonsterLayer(BattlePhase phase, int subFrame) { final monsterFrames = _getAnimatedMonsterFrames( monsterCategory, @@ -155,7 +155,7 @@ class CanvasBattleComposer { ); } - /// 이펙트 레이어 생성 (z=2) + /// 이펙트 레이어 생성 (z=3, 캐릭터/몬스터 위에 표시) AsciiLayer? _createEffectLayer(BattlePhase phase, int subFrame) { final effect = getWeaponEffect(weaponCategory); final effectLines = _getEffectLines(effect, phase, subFrame); @@ -176,7 +176,7 @@ class CanvasBattleComposer { return AsciiLayer( cells: cells, - zIndex: 2, + zIndex: 3, offsetX: effectX, offsetY: effectY, ); diff --git a/lib/src/core/animation/canvas/canvas_walking_composer.dart b/lib/src/core/animation/canvas/canvas_walking_composer.dart index 6dd2b73..bc9bcd1 100644 --- a/lib/src/core/animation/canvas/canvas_walking_composer.dart +++ b/lib/src/core/animation/canvas/canvas_walking_composer.dart @@ -65,12 +65,7 @@ class CanvasWalkingComposer { // 바닥 레이어(Y=7) 위에 서있도록 final charY = frameHeight - cells.length - 1; - return AsciiLayer( - cells: cells, - zIndex: 1, - offsetX: charX, - offsetY: charY, - ); + return AsciiLayer(cells: cells, zIndex: 1, offsetX: charX, offsetY: charY); } /// 문자열 스프라이트를 AsciiCell 2D 배열로 변환 @@ -87,27 +82,11 @@ class CanvasWalkingComposer { const _walkingFrames = [ // 프레임 1: 오른발 앞 - [ - r' o ', - r' /|\ ', - r' / | ', - ], + [r' o ', r' /|\ ', r' /| '], // 프레임 2: 모음 - [ - r' o ', - r' /|\ ', - r' / \ ', - ], + [r' o ', r' /|\ ', r' |\ '], // 프레임 3: 왼발 앞 - [ - r' o ', - r' /|\ ', - r' | \ ', - ], + [r' o ', r' /|\ ', r' /| '], // 프레임 4: 모음 - [ - r' o ', - r' /|\ ', - r' / \ ', - ], + [r' o ', r' /|\ ', r' |\ '], ]; diff --git a/lib/src/features/game/game_play_screen.dart b/lib/src/features/game/game_play_screen.dart index b23ab37..27d6ead 100644 --- a/lib/src/features/game/game_play_screen.dart +++ b/lib/src/features/game/game_play_screen.dart @@ -476,8 +476,11 @@ class _GamePlayScreenState extends State _specialAnimation = AsciiAnimationType.resurrection; }); - // 3. 애니메이션 종료 후 게임 재개 (5프레임 × 600ms = 3초) - Future.delayed(const Duration(milliseconds: 3000), () async { + // 3. 애니메이션 종료 후 게임 재개 + final duration = getSpecialAnimationDuration( + AsciiAnimationType.resurrection, + ); + Future.delayed(Duration(milliseconds: duration), () async { if (mounted) { setState(() { _specialAnimation = null; diff --git a/lib/src/features/game/widgets/ascii_animation_card.dart b/lib/src/features/game/widgets/ascii_animation_card.dart index fae3293..4ac91f5 100644 --- a/lib/src/features/game/widgets/ascii_animation_card.dart +++ b/lib/src/features/game/widgets/ascii_animation_card.dart @@ -118,13 +118,8 @@ class _AsciiAnimationCardState extends State { int? _lastEventTimestamp; bool _showCriticalEffect = false; - // 특수 애니메이션 프레임 수 - static const _specialAnimationFrameCounts = { - AsciiAnimationType.levelUp: 5, - AsciiAnimationType.questComplete: 4, - AsciiAnimationType.actComplete: 4, - AsciiAnimationType.resurrection: 5, - }; + // 특수 애니메이션 프레임 수는 ascii_animation_type.dart의 + // specialAnimationFrameCounts 상수 사용 @override void initState() { @@ -242,7 +237,7 @@ class _AsciiAnimationCardState extends State { if (_animationMode == AnimationMode.special) { _currentFrame++; final maxFrames = - _specialAnimationFrameCounts[_currentSpecialAnimation] ?? 5; + specialAnimationFrameCounts[_currentSpecialAnimation] ?? 5; // 마지막 프레임에 도달하면 특수 애니메이션 종료 if (_currentFrame >= maxFrames) { _currentSpecialAnimation = null;