//-------------------------------------------------------- 
 | 
//    [Author]:           第二世界 
 | 
//    [  Date ]:           Monday, September 11, 2017 
 | 
//-------------------------------------------------------- 
 | 
using UnityEngine; 
 | 
using System.Collections; 
 | 
using UnityEngine.UI; 
 | 
  
 | 
using System.Text; 
 | 
  
 | 
public class BossLifeBar : MonoBehaviour 
 | 
{ 
 | 
    [SerializeField] Sprite[] m_LifeBarSprites; 
 | 
  
 | 
    [SerializeField] Image m_BackGround; 
 | 
    [SerializeField] Image m_MiddleGround; 
 | 
    [SerializeField] Image m_PrefaceGround; 
 | 
  
 | 
    [SerializeField] Slider m_SliderMiddleground; 
 | 
    [SerializeField] Slider m_SliderForeground; 
 | 
  
 | 
    [SerializeField] Text m_Surplus; 
 | 
  
 | 
    [SerializeField] Text m_SurplusPercent; 
 | 
     
 | 
  
 | 
    [SerializeField] float m_SmoothTime = 0.3f; 
 | 
    public float smoothTime { 
 | 
        get { return m_SmoothTime; } 
 | 
    } 
 | 
  
 | 
    Pattern pattern = Pattern.Reduce; 
 | 
    float targetValue = 0f; 
 | 
    int totalSegments = 1; 
 | 
    int surplusSegments = -1; 
 | 
  
 | 
    float refValue = 0f; 
 | 
    float timer = 0f; 
 | 
    float behaviourStartValue = 0f; 
 | 
  
 | 
    float m_CurrentBehaviourValue = 0f; 
 | 
    float currentBehaviourValue { 
 | 
        get { return m_CurrentBehaviourValue; } 
 | 
        set { 
 | 
            m_CurrentBehaviourValue = value; 
 | 
            UpdateSurplusSegments(currentBehaviourValue); 
 | 
  
 | 
            float behaviourDecimalValue = GetSegmentDecimal(m_CurrentBehaviourValue); 
 | 
            float trueDecimalValue = GetSegmentDecimal(targetValue); 
 | 
  
 | 
            switch (pattern) 
 | 
            { 
 | 
                case Pattern.Add: 
 | 
                    m_SliderForeground.value = behaviourDecimalValue; 
 | 
                    m_SliderMiddleground.value = behaviourDecimalValue > trueDecimalValue ? 1f : trueDecimalValue; 
 | 
                    break; 
 | 
                case Pattern.Reduce: 
 | 
                    m_SliderMiddleground.value = behaviourDecimalValue; 
 | 
                    m_SliderForeground.value = behaviourDecimalValue < trueDecimalValue ? 0f : trueDecimalValue; 
 | 
                    break; 
 | 
                case Pattern.None: 
 | 
                    m_SliderMiddleground.value = behaviourDecimalValue; 
 | 
                    m_SliderForeground.value = behaviourDecimalValue; 
 | 
                    break; 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public void SetBaseInfo(int _lifeBarCount, ulong _hp, ulong _maxHp) 
 | 
    { 
 | 
        surplusSegments = -1; 
 | 
        totalSegments = _lifeBarCount; 
 | 
  
 | 
        // 使用精确值,不再人为减小 
 | 
        float percentage = (_maxHp > 0) ? (float)_hp / (float)_maxHp : 0f; 
 | 
        targetValue = currentBehaviourValue = percentage * totalSegments; 
 | 
  
 | 
        // 使用统一的 GetSegmentDecimal,避免小数精度导致进度条为0 
 | 
        var behaviourDecimalValue = GetSegmentDecimal(currentBehaviourValue); 
 | 
        m_SliderForeground.value = m_SliderMiddleground.value = behaviourDecimalValue; 
 | 
  
 | 
        refValue = 0f; 
 | 
  
 | 
        // 立刻显示基准百分比(使用 percentage) 
 | 
        m_SurplusPercent.text = (percentage * 100f).ToString("F2") + "%"; 
 | 
    } 
 | 
  
 | 
    public void Show(ulong _hp, ulong _maxHp) 
 | 
    { 
 | 
        var percentage = Mathf.Clamp(_hp, 0, _maxHp) / (float)_maxHp; 
 | 
        var tempValue = totalSegments * percentage; // 不再减小 
 | 
        pattern = tempValue > targetValue ? Pattern.Add : tempValue < targetValue ? Pattern.Reduce : Pattern.None; 
 | 
  
 | 
        behaviourStartValue = currentBehaviourValue; 
 | 
        targetValue = tempValue; 
 | 
  
 | 
        timer = 0f; 
 | 
        refValue = 0f; 
 | 
  
 | 
        // 立即更新百分比显示(直接使用 percentage) 
 | 
        m_SurplusPercent.text = (percentage * 100f).ToString("F2") + "%"; 
 | 
    } 
 | 
  
 | 
    private void LateUpdate() 
 | 
    { 
 | 
        if (Mathf.Abs(currentBehaviourValue - targetValue) > 0.00001f) 
 | 
        { 
 | 
            var newValue = Mathf.SmoothDamp(currentBehaviourValue, targetValue, ref refValue, smoothTime); 
 | 
            currentBehaviourValue = newValue; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    static StringBuilder stringBuild = new StringBuilder(); 
 | 
    private void UpdateSurplusSegments(float _targetValue) 
 | 
    { 
 | 
        var currentSurplus = Mathf.CeilToInt(_targetValue); 
 | 
        if (currentSurplus != surplusSegments) 
 | 
        { 
 | 
            surplusSegments = currentSurplus; 
 | 
            var colorSetLength = m_LifeBarSprites.Length; 
 | 
            var index = surplusSegments % colorSetLength; 
 | 
            var nextIndex = index == 0 ? colorSetLength - 1 : index - 1; 
 | 
  
 | 
            m_PrefaceGround.overrideSprite = m_LifeBarSprites[index]; 
 | 
            m_MiddleGround.overrideSprite = m_LifeBarSprites[index]; 
 | 
            m_BackGround.overrideSprite = m_LifeBarSprites[nextIndex]; 
 | 
  
 | 
            m_BackGround.SetActive(surplusSegments > 1); 
 | 
  
 | 
            m_Surplus.text = "x" + surplusSegments.ToString(); 
 | 
            float pct = totalSegments > 0 ? Mathf.Clamp01(_targetValue / totalSegments) : 0f; 
 | 
            // 修复格式并处理接近 100% 的情况 
 | 
            if (1f - pct < 0.00005f) pct = 1f; 
 | 
            m_SurplusPercent.text = (pct * 100f).ToString("F2") + "%"; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    // int GetNumKey(int _num) 
 | 
    // { 
 | 
    //     var config = DamageNumConfig.Get("BossLifeBarSurplusNum"); 
 | 
    //     return config.nums[_num - 48]; 
 | 
    // } 
 | 
  
 | 
  
 | 
    enum Pattern 
 | 
    { 
 | 
        None, 
 | 
        Add, 
 | 
        Reduce, 
 | 
    } 
 | 
  
 | 
    // helper: 返回段内小数部分;当恰好为整数且大于0时,返回1以表示满格(避免0导致进度条变空) 
 | 
    private float GetSegmentDecimal(float value) 
 | 
    { 
 | 
        // 先判断是否为 0,避免被误判为"整段满格" 
 | 
        if (value <= 0f) return 0f; 
 | 
  
 | 
        // 使用一个小的容忍值来处理浮点误差,避免 near-integer 导致 0 
 | 
        const float eps = 1e-5f; 
 | 
  
 | 
        // 先做一个向下稳定的 floor,避免 2.999999 变成 2 的问题 
 | 
        float stableFloor = Mathf.Floor(value + eps); 
 | 
        float frac = value - stableFloor; 
 | 
  
 | 
        // 只有在 value > 0 且接近整数时才返回 1(表示当前段满格) 
 | 
        if (frac <= eps && value >= 1f - eps) 
 | 
            return 1f; 
 | 
         
 | 
        return Mathf.Clamp01(frac); 
 | 
    } 
 | 
  
 | 
} 
 |