yyl
1 天以前 7f9ec6d10ebb5d741b10e2b4168b11ad0ebb22cd
Main/System/Battle/BattleHUDWin.cs
@@ -10,6 +10,10 @@
//  这个界面是 persistent的界面
public class BattleHUDWin : UIBase
{
    private const int CASTER_DAMAGE_HEIGHT_OFFSET = 100; // 施法者伤害高度间隔
    private const int CASTER_DAMAGE_FLOAT_HEIGHT = 150;  // 飘字向上移动高度
    private const int TARGET_DAMAGE_FLOAT_HEIGHT = 150;  // 目标伤害飘字向上移动高度
    private GameObjectPoolManager.GameObjectPool damagePrefabPool;
    private GameObjectPoolManager.GameObjectPool buffIconPrefabPool;
    private GameObjectPoolManager.GameObjectPool buffLabelPrefabPool;
@@ -29,35 +33,14 @@
    protected override void OnPreOpen()
    {
        base.OnPreOpen();
        EventBroadcast.Instance.AddListener<BattleDmgInfo>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.AddListener<string, JsonData>(EventName.BATTLE_END, OnBattleEnd);
        damagePrefabPool = GameObjectPoolManager.Instance.RequestPool(UILoader.LoadPrefab("DamageContent"));
    }
    private void OnBattleEnd(string guid, JsonData data)
    {
        ClearContent(guid);
    }
    private void ClearContent(string guid, bool force = false)
    {
        if ((battleField != null && battleField.guid == guid) || force)
        {
            for (int i = damageContentList.Count - 1; i >= 0; i--)
            {
                var content = damageContentList[i];
                content.Stop();
                RemoveDamageContent(content);
            }
            damageContentList.Clear();
        }
        RegisterEvents();
        InitializePools();
    }
    protected override void OnPreClose()
    {
        base.OnPreClose();
        EventBroadcast.Instance.RemoveListener<BattleDmgInfo>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.RemoveListener<string, JsonData>(EventName.BATTLE_END, OnBattleEnd);
        UnregisterEvents();
    }
    protected override void OnOpen()
@@ -68,13 +51,7 @@
    protected override void OnClose()
    {
        base.OnClose();
        if (battleField != null)
        {
            battleField.OnBattlePause -= OnBattlePause;
            battleField.OnBattleRun -= OnBattleRun;
            battleField.OnSpeedRatioChange -= OnSpeedRatioChange;
            battleField = null;
        }
        CleanupBattleField();
    }
    protected override void NextFrameAfterOpen()
@@ -87,121 +64,65 @@
        base.CompleteClose();
    }
    private void RemoveDamageContent(DamageContent content)
    private void RegisterEvents()
    {
        damageContentList.Remove(content);
        damagePrefabPool.Release(content.gameObject);
        EventBroadcast.Instance.AddListener<BattleDmgInfo>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.AddListener<string, JsonData>(EventName.BATTLE_END, OnBattleEnd);
    }
    private void UnregisterEvents()
    {
        EventBroadcast.Instance.RemoveListener<BattleDmgInfo>(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken);
        EventBroadcast.Instance.RemoveListener<string, JsonData>(EventName.BATTLE_END, OnBattleEnd);
    }
    private void InitializePools()
    {
        damagePrefabPool = GameObjectPoolManager.Instance.RequestPool(UILoader.LoadPrefab("DamageContent"));
    }
    public void SetBattleField(BattleField _battleField)
    {
        CleanupBattleField();
        ClearContent(string.Empty, true);
        battleField = _battleField;
        RegisterBattleFieldEvents();
    }
    private void RegisterBattleFieldEvents()
    {
        if (battleField == null) return;
        battleField.OnBattlePause += OnBattlePause;
        battleField.OnBattleRun += OnBattleRun;
        battleField.OnSpeedRatioChange += OnSpeedRatioChange;
    }
    private void UnregisterBattleFieldEvents()
    {
        if (battleField == null) return;
        battleField.OnBattlePause -= OnBattlePause;
        battleField.OnBattleRun -= OnBattleRun;
        battleField.OnSpeedRatioChange -= OnSpeedRatioChange;
    }
    private void CleanupBattleField()
    {
        UnregisterBattleFieldEvents();
        battleField = null;
    }
    private void OnBattleEnd(string guid, JsonData data)
    {
        ClearContent(guid);
    }
    private void OnDamageTaken(BattleDmgInfo damageInfo)
    {
        SetTargetDamage(damageInfo);
        SetSelfDamage(damageInfo);
    }
    private void SetSelfDamage(BattleDmgInfo damageInfo)
    {
        if (damageInfo.casterDamageList.Count > 0)
        {
            GameObject damageContent = damagePrefabPool.Request();
            DamageContent content = damageContent.GetComponent<DamageContent>();
            damageContent.transform.SetParent(damageNode, false);
            var heroRect = damageInfo.casterObj.heroRectTrans;
            if (heroRect == null)
            {
                damagePrefabPool.Release(damageContent);
                return;
            }
            var contentRect = content.GetComponent<RectTransform>();
            var contentParentRect = contentRect.parent as RectTransform;
            // 获取 heroRect 的世界坐标(锚点为中心)
            Vector3 worldTargetPos = heroRect.transform.TransformPoint(heroRect.rect.center);
            // 转换到 content 父节点下的 anchoredPosition
            Vector2 anchoredPos;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                contentParentRect,
                RectTransformUtility.WorldToScreenPoint(null, worldTargetPos),
                null,
                out anchoredPos);
            // 设置动态位置(会覆盖配置中的位置)
            Vector2 beginPos = anchoredPos;
            Vector2 endPos = anchoredPos + new Vector2(0, 150);
            content.SetPosition(beginPos, endPos);
            // 设置速度比例
            if (battleField != null)
            {
                content.SetRatio(battleField.speedRatio, 1f);
            }
            content.SetDamage(damageInfo, damageInfo.casterDamageList, () => RemoveDamageContent(content));
            damageContentList.Add(content);
        }
    }
    private void SetTargetDamage(BattleDmgInfo damageInfo)
    {
        if (damageInfo.targetDamageList.Count > 0)
        {
            GameObject damageContent = damagePrefabPool.Request();
            DamageContent content = damageContent.GetComponent<DamageContent>();
            damageContent.transform.SetParent(damageNode, false);
            var heroRect = damageInfo.hurtObj.heroRectTrans;
            if (heroRect == null)
            {
                damagePrefabPool.Release(damageContent);
                return;
            }
            var contentRect = content.GetComponent<RectTransform>();
            var contentParentRect = contentRect.parent as RectTransform;
            // 获取 heroRect 的世界坐标(锚点为中心)
            Vector3 worldTargetPos = heroRect.transform.TransformPoint(heroRect.rect.center);
            // 转换到 content 父节点下的 anchoredPosition
            Vector2 anchoredPos;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                contentParentRect,
                RectTransformUtility.WorldToScreenPoint(null, worldTargetPos),
                null,
                out anchoredPos);
            // 设置动态位置(会覆盖配置中的位置)
            Vector2 beginPos = anchoredPos;
            Vector2 endPos = anchoredPos + new Vector2(0, 150);
            content.SetPosition(beginPos, endPos);
            // 设置速度比例
            if (battleField != null)
            {
                content.SetRatio(battleField.speedRatio, 1f);
            }
            content.SetDamage(damageInfo, damageInfo.targetDamageList, () => RemoveDamageContent(content));
            damageContentList.Add(content);
        }
    }
    public void SetBattleField(BattleField _battleField)
    {
        if (battleField != null)
        {
            battleField.OnBattlePause -= OnBattlePause;
            battleField.OnBattleRun -= OnBattleRun;
            battleField.OnSpeedRatioChange -= OnSpeedRatioChange;
        }
        ClearContent(string.Empty, true);
        battleField = _battleField;
        battleField.OnBattlePause += OnBattlePause;
        battleField.OnBattleRun += OnBattleRun;
        battleField.OnSpeedRatioChange += OnSpeedRatioChange;
    }
    private void OnSpeedRatioChange(float newSpeedRatio)
@@ -216,22 +137,167 @@
    {
        if (isPause)
        {
            foreach (var content in damageContentList)
            {
                content.Stop();
            }
            PauseAllDamageContent();
        }
        else
        {
            foreach (var content in damageContentList)
            {
                content.Resume();
            }
            ResumeAllDamageContent();
        }
    }
    private void OnBattleRun()
    {
        RunAllDamageContent();
    }
    /// <summary>
    /// 设置目标受到的伤害显示
    /// </summary>
    private void SetTargetDamage(BattleDmgInfo damageInfo)
    {
        if (damageInfo.targetDamageList.Count == 0) return;
        RectTransform heroRect = damageInfo.hurtObj.heroRectTrans;
        if (heroRect == null) return;
        DamageContent content = CreateDamageContent();
        if (content == null) return;
        Vector2 anchoredPos = CalculateWorldToLocalPosition(heroRect, content);
        SetupTargetDamagePosition(content, anchoredPos);
        SetupDamageContent(content, damageInfo.targetDamageList, damageInfo);
    }
    /// <summary>
    /// 设置目标伤害的起始和结束位置
    /// </summary>
    private void SetupTargetDamagePosition(DamageContent content, Vector2 anchoredPos)
    {
        // 保持英雄的 X 坐标,只在 Y 轴向上飘
        Vector2 beginPos = anchoredPos;
        Vector2 endPos = anchoredPos + new Vector2(0, TARGET_DAMAGE_FLOAT_HEIGHT);
        content.SetPosition(beginPos, endPos);
    }
    /// <summary>
    /// 设置施法者受到的伤害显示(反伤、吸血等)
    /// </summary>
    private void SetSelfDamage(BattleDmgInfo damageInfo)
    {
        if (damageInfo.casterDamageList.Count == 0) return;
        RectTransform heroRect = damageInfo.casterObj.heroRectTrans;
        if (heroRect == null) return;
        // 创建单个DamageContent显示所有施法者伤害
        DamageContent content = CreateDamageContent();
        if (content == null) return;
        Vector2 anchoredPos = CalculateWorldToLocalPosition(heroRect, content);
        SetupCasterDamagePosition(content, anchoredPos);
        SetupDamageContent(content, damageInfo.casterDamageList, damageInfo);
    }
    /// <summary>
    /// 设置施法者伤害的起始和结束位置
    /// </summary>
    private void SetupCasterDamagePosition(DamageContent content, Vector2 anchoredPos)
    {
        // 保持英雄的 X 坐标,只在 Y 轴向上飘
        Vector2 beginPos = anchoredPos;
        Vector2 endPos = anchoredPos + new Vector2(0, CASTER_DAMAGE_FLOAT_HEIGHT);
        content.SetPosition(beginPos, endPos);
    }
    /// <summary>
    /// 创建一个DamageContent对象
    /// </summary>
    private DamageContent CreateDamageContent()
    {
        GameObject damageContentObj = damagePrefabPool.Request();
        DamageContent content = damageContentObj.GetComponent<DamageContent>();
        damageContentObj.transform.SetParent(damageNode, false);
        return content;
    }
    /// <summary>
    /// 计算英雄世界坐标到本地坐标的转换
    /// </summary>
    private Vector2 CalculateWorldToLocalPosition(RectTransform heroRect, DamageContent content)
    {
        RectTransform contentRect = content.GetComponent<RectTransform>();
        RectTransform contentParentRect = contentRect.parent as RectTransform;
        Vector3 worldTargetPos = heroRect.transform.TransformPoint(heroRect.rect.center);
        Vector2 anchoredPos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            contentParentRect,
            RectTransformUtility.WorldToScreenPoint(null, worldTargetPos),
            null,
            out anchoredPos);
        return anchoredPos;
    }
    /// <summary>
    /// 配置DamageContent的速度、伤害数据和回调
    /// </summary>
    private void SetupDamageContent(DamageContent content, List<BattleDmg> damageList, BattleDmgInfo damageInfo)
    {
        if (battleField != null)
        {
            content.SetRatio(battleField.speedRatio, 1f);
        }
        content.SetDamage(damageInfo, damageList, () => RemoveDamageContent(content));
        damageContentList.Add(content);
    }
    /// <summary>
    /// 移除DamageContent对象
    /// </summary>
    private void RemoveDamageContent(DamageContent content)
    {
        damageContentList.Remove(content);
        damagePrefabPool.Release(content.gameObject);
    }
    /// <summary>
    /// 清除所有伤害显示内容
    /// </summary>
    private void ClearContent(string guid, bool force = false)
    {
        if ((battleField != null && battleField.guid == guid) || force)
        {
            for (int i = damageContentList.Count - 1; i >= 0; i--)
            {
                var content = damageContentList[i];
                content.Stop();
                RemoveDamageContent(content);
            }
            damageContentList.Clear();
        }
    }
    private void PauseAllDamageContent()
    {
        foreach (var content in damageContentList)
        {
            content.Stop();
        }
    }
    private void ResumeAllDamageContent()
    {
        foreach (var content in damageContentList)
        {
            content.Resume();
        }
    }
    private void RunAllDamageContent()
    {
        for (int i = damageContentList.Count - 1; i >= 0; i--)
        {
            if (i < damageContentList.Count)