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<DamageContent> damageContentList = new List<DamageContent>();
|
|
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<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 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();
|
}
|
|
/// <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)
|
{
|
damageContentList[i].Run();
|
}
|
}
|
}
|
}
|