using UnityEngine;
using UnityEngine.UI;
namespace Streamingle.Contents.BossRaid
{
///
/// 보스 HP바 UI. 고전 RPG (포켓몬) 스타일.
/// 얇고 긴 게이지 + 이름판 + HP 수치.
///
public class BossHPBar : MonoBehaviour
{
#region Fields
[Header("UI 참조 (자동 생성 가능)")]
[SerializeField] private Canvas canvas;
[SerializeField] private Image hpFill;
[SerializeField] private Image hpDamageFill;
[SerializeField] private Text bossNameText;
[SerializeField] private Text hpText;
[SerializeField] private Text hpValueText;
[Header("설정")]
[SerializeField] private float smoothSpeed = 5f;
[SerializeField] private float damageShowDelay = 0.4f;
[SerializeField] private float damageSmooth = 3f;
[Header("색상")]
[SerializeField] private Color hpColorHigh = new Color(0.18f, 0.82f, 0.28f);
[SerializeField] private Color hpColorMid = new Color(0.95f, 0.78f, 0.1f);
[SerializeField] private Color hpColorLow = new Color(0.92f, 0.2f, 0.15f);
[SerializeField] private Color damageTrailColor = new Color(0.9f, 0.35f, 0.1f, 0.9f);
private float _targetRatio = 1f;
private float _currentDisplayRatio = 1f;
private float _damageDisplayRatio = 1f;
private float _damageTimer;
private bool _isVisible;
private Font _font;
private RectTransform _hpFillRect;
private RectTransform _dmgFillRect;
private int _maxHP;
// 프레임 색상 (고전 RPG 도트 느낌)
private static readonly Color FrameOuter = new Color(0.12f, 0.12f, 0.18f, 1f);
private static readonly Color FrameInner = new Color(0.35f, 0.35f, 0.42f, 1f);
private static readonly Color FrameHighlight = new Color(0.55f, 0.55f, 0.65f, 0.5f);
private static readonly Color NameplateBG = new Color(0.08f, 0.08f, 0.15f, 0.92f);
private static readonly Color GaugeBG = new Color(0.02f, 0.02f, 0.05f, 1f);
#endregion
#region Unity Messages
private void Awake()
{
_font = BossRaidFontLoader.Load();
if (canvas == null || hpFill == null)
CreateUI();
Hide();
}
private void Update()
{
if (!_isVisible) return;
_currentDisplayRatio = Mathf.Lerp(_currentDisplayRatio, _targetRatio, Time.deltaTime * smoothSpeed);
SetFillWidth(_hpFillRect, _currentDisplayRatio);
hpFill.color = GetHPColor(_currentDisplayRatio);
_damageTimer -= Time.deltaTime;
if (_damageTimer <= 0f)
_damageDisplayRatio = Mathf.Lerp(_damageDisplayRatio, _currentDisplayRatio, Time.deltaTime * damageSmooth);
SetFillWidth(_dmgFillRect, _damageDisplayRatio);
if (hpText != null)
{
int displayPercent = Mathf.RoundToInt(_currentDisplayRatio * 100f);
hpText.text = $"{displayPercent}%";
}
if (hpValueText != null)
{
int displayHP = Mathf.RoundToInt(_currentDisplayRatio * _maxHP);
hpValueText.text = $"{displayHP} / {_maxHP}";
}
}
#endregion
#region Public Methods
public void Show(string bossName, float hpRatio = 1f, int maxHP = 0)
{
_isVisible = true;
_targetRatio = hpRatio;
_currentDisplayRatio = hpRatio;
_damageDisplayRatio = hpRatio;
_maxHP = maxHP;
if (bossNameText != null)
bossNameText.text = bossName;
if (canvas != null)
canvas.gameObject.SetActive(true);
}
public void Hide()
{
_isVisible = false;
if (canvas != null)
canvas.gameObject.SetActive(false);
}
public void SetHP(float ratio, int currentHP = -1, int maxHP = -1)
{
_targetRatio = Mathf.Clamp01(ratio);
_damageTimer = damageShowDelay;
if (maxHP > 0) _maxHP = maxHP;
}
#endregion
#region Private Methods
private void SetFillWidth(RectTransform rect, float ratio)
{
if (rect == null) return;
rect.anchorMax = new Vector2(Mathf.Clamp01(ratio), rect.anchorMax.y);
}
private Color GetHPColor(float ratio)
{
if (ratio > 0.5f)
return Color.Lerp(hpColorMid, hpColorHigh, (ratio - 0.5f) * 2f);
else
return Color.Lerp(hpColorLow, hpColorMid, ratio * 2f);
}
private void CreateUI()
{
// ━━━ Canvas ━━━
var canvasObj = new GameObject("BossRaid_HPBar");
canvasObj.transform.SetParent(transform);
canvas = canvasObj.AddComponent