using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using DG.Tweening; using Cysharp.Threading.Tasks; using System; using LitJson; // 这个界面是 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; public Transform damageNode; public Transform buffIconNode; public Transform buffLabelNode; private BattleField battleField; private List damageContentList = new List(); protected override void InitComponent() { base.InitComponent(); } protected override void OnPreOpen() { base.OnPreOpen(); RegisterEvents(); InitializePools(); } protected override void OnPreClose() { base.OnPreClose(); UnregisterEvents(); } protected override void OnOpen() { base.OnOpen(); } protected override void OnClose() { base.OnClose(); CleanupBattleField(); } protected override void NextFrameAfterOpen() { base.NextFrameAfterOpen(); } protected override void CompleteClose() { base.CompleteClose(); } private void RegisterEvents() { EventBroadcast.Instance.AddListener(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken); EventBroadcast.Instance.AddListener(EventName.BATTLE_END, OnBattleEnd); } private void UnregisterEvents() { EventBroadcast.Instance.RemoveListener(EventName.BATTLE_DAMAGE_TAKEN, OnDamageTaken); EventBroadcast.Instance.RemoveListener(EventName.BATTLE_END, OnBattleEnd); } private void InitializePools() { damagePrefabPool = GameObjectPoolManager.Instance.GetPool(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 OnSpeedRatioChange(float newSpeedRatio) { foreach (var content in damageContentList) { content.SetRatio(newSpeedRatio, 1f); } } private void OnBattlePause(bool isPause) { if (isPause) { PauseAllDamageContent(); } else { ResumeAllDamageContent(); } } private void OnBattleRun() { RunAllDamageContent(); } /// /// 设置目标受到的伤害显示 /// 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); } /// /// 设置目标伤害的起始和结束位置 /// 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); } /// /// 设置施法者受到的伤害显示(反伤、吸血等) /// 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); } /// /// 设置施法者伤害的起始和结束位置 /// 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); } /// /// 创建一个DamageContent对象 /// private DamageContent CreateDamageContent() { GameObject damageContentObj = damagePrefabPool.Request(); DamageContent content = damageContentObj.GetComponent(); damageContentObj.transform.SetParent(damageNode, false); return content; } /// /// 计算英雄世界坐标到本地坐标的转换 /// private Vector2 CalculateWorldToLocalPosition(RectTransform heroRect, DamageContent content) { RectTransform contentRect = content.GetComponent(); 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; } /// /// 配置DamageContent的速度、伤害数据和回调 /// private void SetupDamageContent(DamageContent content, List damageList, BattleDmgInfo damageInfo) { if (battleField != null) { content.SetRatio(battleField.speedRatio, 1f); } content.SetDamage(damageInfo, damageList, () => RemoveDamageContent(content)); damageContentList.Add(content); } /// /// 移除DamageContent对象 /// private void RemoveDamageContent(DamageContent content) { damageContentList.Remove(content); damagePrefabPool.Release(content.gameObject); } /// /// 清除所有伤害显示内容 /// 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) { damageContentList[i].Run(); } } } }