From 9599a33a8fc52e94fe9635b95bfb00007a537ca4 Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Thu, 15 Jan 2026 23:23:02 +0900 Subject: [PATCH] =?UTF-8?q?style(ui):=20HP/MP=20=EB=B0=94=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=20=EC=98=A4=EB=B2=84=EB=A0=88=EC=9D=B4=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 웹: hp_mp_bar.dart 숫자를 바 중앙에 오버레이 - 모바일: enhanced_animation_panel.dart 동일 적용 - 텍스트 그림자 추가로 가독성 향상 --- .../widgets/enhanced_animation_panel.dart | 116 +++++++++++------- lib/src/features/game/widgets/hp_mp_bar.dart | 99 ++++++++------- 2 files changed, 126 insertions(+), 89 deletions(-) diff --git a/lib/src/features/game/widgets/enhanced_animation_panel.dart b/lib/src/features/game/widgets/enhanced_animation_panel.dart index c9f0784..6846c7f 100644 --- a/lib/src/features/game/widgets/enhanced_animation_panel.dart +++ b/lib/src/features/game/widgets/enhanced_animation_panel.dart @@ -285,7 +285,7 @@ class _EnhancedAnimationPanelState extends State ); } - /// 컴팩트 HP 바 + /// 컴팩트 HP 바 (숫자 오버레이) Widget _buildCompactHpBar() { final ratio = _currentHpMax > 0 ? _currentHp / _currentHpMax : 0.0; final isLow = ratio < 0.2 && ratio > 0; @@ -320,29 +320,42 @@ class _EnhancedAnimationPanelState extends State ), ), ), - // 프로그레스 + // 프로그레스 바 + 숫자 오버레이 Expanded( - child: ClipRRect( - borderRadius: const BorderRadius.horizontal( - right: Radius.circular(3), - ), - child: LinearProgressIndicator( - value: ratio.clamp(0.0, 1.0), - backgroundColor: Colors.red.withValues(alpha: 0.2), - valueColor: AlwaysStoppedAnimation( - isLow ? Colors.red : Colors.red.shade600, + child: Stack( + alignment: Alignment.center, + children: [ + // 프로그레스 바 + ClipRRect( + borderRadius: const BorderRadius.horizontal( + right: Radius.circular(3), + ), + child: LinearProgressIndicator( + value: ratio.clamp(0.0, 1.0), + backgroundColor: Colors.red.withValues(alpha: 0.2), + valueColor: AlwaysStoppedAnimation( + isLow ? Colors.red : Colors.red.shade600, + ), + minHeight: 20, + ), ), - minHeight: 20, - ), - ), - ), - // 수치 - Container( - width: 56, - alignment: Alignment.center, - child: Text( - '$_currentHp/$_currentHpMax', - style: const TextStyle(fontSize: 11, color: Colors.white), + // 숫자 오버레이 (바 중앙) + Text( + '$_currentHp/$_currentHpMax', + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.bold, + color: Colors.white, + shadows: [ + Shadow( + color: Colors.black.withValues(alpha: 0.9), + blurRadius: 2, + ), + const Shadow(color: Colors.black, blurRadius: 4), + ], + ), + ), + ], ), ), ], @@ -352,7 +365,7 @@ class _EnhancedAnimationPanelState extends State // 플로팅 변화량 if (_hpChange != 0 && _hpFlashAnimation.value > 0.05) Positioned( - right: 50, + right: 20, top: -8, child: Transform.translate( offset: Offset(0, -10 * (1 - _hpFlashAnimation.value)), @@ -378,7 +391,7 @@ class _EnhancedAnimationPanelState extends State ); } - /// 컴팩트 MP 바 + /// 컴팩트 MP 바 (숫자 오버레이) Widget _buildCompactMpBar() { final ratio = _currentMpMax > 0 ? _currentMp / _currentMpMax : 0.0; @@ -408,27 +421,42 @@ class _EnhancedAnimationPanelState extends State ), ), ), + // 프로그레스 바 + 숫자 오버레이 Expanded( - child: ClipRRect( - borderRadius: const BorderRadius.horizontal( - right: Radius.circular(3), - ), - child: LinearProgressIndicator( - value: ratio.clamp(0.0, 1.0), - backgroundColor: Colors.blue.withValues(alpha: 0.2), - valueColor: AlwaysStoppedAnimation( - Colors.blue.shade600, + child: Stack( + alignment: Alignment.center, + children: [ + // 프로그레스 바 + ClipRRect( + borderRadius: const BorderRadius.horizontal( + right: Radius.circular(3), + ), + child: LinearProgressIndicator( + value: ratio.clamp(0.0, 1.0), + backgroundColor: Colors.blue.withValues(alpha: 0.2), + valueColor: AlwaysStoppedAnimation( + Colors.blue.shade600, + ), + minHeight: 20, + ), ), - minHeight: 20, - ), - ), - ), - Container( - width: 56, - alignment: Alignment.center, - child: Text( - '$_currentMp/$_currentMpMax', - style: const TextStyle(fontSize: 11, color: Colors.white), + // 숫자 오버레이 (바 중앙) + Text( + '$_currentMp/$_currentMpMax', + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.bold, + color: Colors.white, + shadows: [ + Shadow( + color: Colors.black.withValues(alpha: 0.9), + blurRadius: 2, + ), + const Shadow(color: Colors.black, blurRadius: 4), + ], + ), + ), + ], ), ), ], @@ -437,7 +465,7 @@ class _EnhancedAnimationPanelState extends State if (_mpChange != 0 && _mpFlashAnimation.value > 0.05) Positioned( - right: 50, + right: 20, top: -8, child: Transform.translate( offset: Offset(0, -10 * (1 - _mpFlashAnimation.value)), diff --git a/lib/src/features/game/widgets/hp_mp_bar.dart b/lib/src/features/game/widgets/hp_mp_bar.dart index b327a50..451042f 100644 --- a/lib/src/features/game/widgets/hp_mp_bar.dart +++ b/lib/src/features/game/widgets/hp_mp_bar.dart @@ -288,7 +288,7 @@ class _HpMpBarState extends State with TickerProviderStateMixin { ); } - /// 레트로 스타일 세그먼트 바 + /// 레트로 스타일 세그먼트 바 (숫자 바 위 오버레이) Widget _buildRetroBar({ required String label, required int current, @@ -316,53 +316,62 @@ class _HpMpBarState extends State with TickerProviderStateMixin { ), ), ), - // 세그먼트 바 + // 세그먼트 바 (숫자 오버레이) Expanded( - child: Container( - height: 12, - decoration: BoxDecoration( - color: emptyColor.withValues(alpha: 0.3), - border: Border.all(color: RetroColors.panelBorderOuter, width: 1), - ), - child: Row( - children: List.generate(segmentCount, (index) { - final isFilled = index < filledSegments; - return Expanded( - child: Container( - decoration: BoxDecoration( - color: isFilled - ? fillColor.withValues(alpha: blinkOpacity) - : emptyColor.withValues(alpha: 0.2), - border: Border( - right: index < segmentCount - 1 - ? BorderSide( - color: RetroColors.panelBorderOuter.withValues( - alpha: 0.3, - ), - width: 1, - ) - : BorderSide.none, + child: Stack( + alignment: Alignment.center, + children: [ + // 세그먼트 바 + Container( + height: 14, + decoration: BoxDecoration( + color: emptyColor.withValues(alpha: 0.3), + border: + Border.all(color: RetroColors.panelBorderOuter, width: 1), + ), + child: Row( + children: List.generate(segmentCount, (index) { + final isFilled = index < filledSegments; + return Expanded( + child: Container( + decoration: BoxDecoration( + color: isFilled + ? fillColor.withValues(alpha: blinkOpacity) + : emptyColor.withValues(alpha: 0.2), + border: Border( + right: index < segmentCount - 1 + ? BorderSide( + color: + RetroColors.panelBorderOuter.withValues( + alpha: 0.3, + ), + width: 1, + ) + : BorderSide.none, + ), + ), ), + ); + }), + ), + ), + // 숫자 오버레이 (바 중앙) + Text( + '$current/$max', + style: TextStyle( + fontFamily: 'PressStart2P', + fontSize: 12, + color: RetroColors.textLight.withValues(alpha: blinkOpacity), + shadows: [ + Shadow( + color: Colors.black.withValues(alpha: 0.9), + blurRadius: 2, ), - ), - ); - }), - ), - ), - ), - const SizedBox(width: 6), - // 수치 표시 - SizedBox( - width: 60, - child: Text( - '$current/$max', - style: const TextStyle( - fontFamily: 'PressStart2P', - fontSize: 13, - color: RetroColors.textLight, - ), - textAlign: TextAlign.right, - overflow: TextOverflow.ellipsis, + const Shadow(color: Colors.black, blurRadius: 4), + ], + ), + ), + ], ), ), ],