123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- using FairyGUI;
- using FL.Battle;
- using FL.Map.UI;
- using FL.Nodes.GameMain;
- using System.Collections.Generic;
- using UnityEngine;
- using XGame;
- using XGame.Database;
- using XGame.Framework.Asyncs;
- using XGame.Framework.Components;
- using XGame.Framework.Interfaces;
- using XGame.Framework.Map;
- using XGame.Framework.Time;
- namespace FL.Map.TestMainMap
- {
- public interface IMapUIContext
- {
- IMapAssetModule Asset { get; }
- ITimeModule Time { get; }
- TestMainMapVM VM { get; }
- }
- /// <summary>
- /// 地图用UI
- /// </summary>
- public class MapUIComponent : Component<IMapUIContext>, ILateUpdate
- {
- private MainMapUIView _uiView;
- private IAsync _uiViewAsync;
- /// <summary>
- /// 玩家、怪物血条
- /// </summary>
- private Dictionary<long, EntityBattleInfoView> _entityViewsMap = new Dictionary<long, EntityBattleInfoView>();
- /// <summary>
- /// 飘血计时
- /// 同一个Entity的飘血需要有200毫秒间隔
- /// </summary>
- private Dictionary<long, long> _hpAddLastTimeMap = new Dictionary<long, long>();
- private HashSet<ITimer> _hpAddTimers = new();
- /// <summary>
- /// TODO
- /// </summary>
- private Camera UICamera => StageCamera.main;
- private int _chapterId;
- private bool _isMasking;
- protected override void OnEnable(object intent)
- {
- EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapStartMask, OnStartMask);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapEndMask, OnEndMask);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapHpAdd, OnHpAdd);
- EventSingle.Instance.AddListener(EventDefine.GameMainMapBossStart, OnBossStart);
- LoadUIView();
- }
- protected override void OnDisable()
- {
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapStartMask, OnStartMask);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapEndMask, OnEndMask);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapHpAdd, OnHpAdd);
- EventSingle.Instance.RemoveListener(EventDefine.GameMainMapBossStart, OnBossStart);
- if (_uiView != null)
- {
- Context.Asset.Recycle(_uiView);
- _uiView = null;
- }
- if (_uiViewAsync != null)
- {
- _uiViewAsync.RemoveAll();
- _uiViewAsync = null;
- }
- ClearEntities(true);
- _chapterId = 0;
- _isMasking = false;
- }
- protected override void OnDispose()
- {
- }
- void ILateUpdate.LateUpdate(int millisecond)
- {
- if (_entityViewsMap.Count > 0)
- {
- var cameraMoving = Context.VM.Camera.IsMoving;
- foreach (var view in _entityViewsMap.Values)
- {
- if ((cameraMoving || view.Master.IsMoving) && view.IsMoveable)
- {
- view.LocalPosition = WorldToLocal(view.Master.UIPoint.position, _uiView.PlayerRoot);
- }
- view.RefreshBuffs();
- }
- }
- _uiView?.LateUpdate(millisecond);
- }
- /// <summary>
- /// 世界坐标转指定UI节点的相对坐标
- /// </summary>
- /// <param name="position"></param>
- /// <param name="parent"></param>
- /// <returns></returns>
- private Vector2 WorldToLocal(Vector3 position, Transform parent)
- {
- var screenPoint = Context.VM.Camera.WorldToScreenPoint(position);
- RectTransformUtility.ScreenPointToLocalPointInRectangle(parent as RectTransform, screenPoint, UICamera, out var localPoint);
- return localPoint;
- }
- public void AddEntity(ITarget master)
- {
- if (_uiView == null)
- {
- if (_uiViewAsync != null)
- {
- _uiViewAsync.On(_ =>
- {
- LoadEntityView(master);
- });
- }
- else
- {
- Log.Error($"MainMapUI不能为空.");
- }
- }
- else
- {
- LoadEntityView(master);
- }
- }
- public void RefreshEntity(long entityId)
- {
- if (_entityViewsMap.TryGetValue(entityId, out var view))
- {
- view.RefreshHp();
- }
- }
- private void LoadEntityView(ITarget master)
- {
- GetEntityAddressable(master, out var addressable, out var parent, out var isBoss);
- var viewAsync = Context.Asset.LoadEntity<EntityBattleInfoView>(addressable, parent);
- viewAsync.On(_ =>
- {
- var view = viewAsync.Result;
- if (view == null)
- return;
- if (master.IsDead)
- {
- Log.Debug($"EntityBattleInfoView 加载完成,Entity已经死亡. Id:{master.Entity.EntityId}");
- Context.Asset.Recycle(view);
- return;
- }
- view.Master = master;
- view.IsMoveable = !isBoss;
- view.LocalPosition = isBoss ? Vector3.zero : WorldToLocal(master.UIPoint.position, _uiView.PlayerRoot);
- _entityViewsMap.Add(view.Master.Entity.EntityId, view);
- });
- }
- private void GetEntityAddressable(ITarget master, out string addressableName, out Transform parent, out bool isBoss)
- {
- isBoss = false;
- if (master.Entity.EntityType == EEntityType.Monster)
- {
- var table = MonsterTableRepo.Get(master.Entity.TableId);
- if (table.Type == 2)
- {
- addressableName = AddressableDefine.bossbattleinfo;
- parent = _uiView.BossRoot;
- isBoss = true;
- }
- else
- {
- addressableName = AddressableDefine.monsterbattleinfo;
- parent = _uiView.MonsterRoot;
- }
- }
- else
- {
- addressableName = AddressableDefine.playerbattleinfo;
- parent = _uiView.PlayerRoot;
- }
- }
- private void OnRemoveEntity(int eventId, object args)
- {
- var entityId = (long)args;
- if (_entityViewsMap.TryGetValue(entityId, out var view))
- {
- if (view.Master.Entity.EntityType == EEntityType.Player)
- { // 玩家的血条不移除
- return;
- }
- _entityViewsMap.Remove(entityId);
- Context.Asset.Recycle(view);
- }
- _hpAddLastTimeMap.Remove(entityId);
- }
- private void OnStartMask(int eventId, object args)
- {
- var sign = (EMapCombatSign)args; //0表示战斗胜利,1表示普通战斗失败,2表示boss战斗失败
- if ( sign != EMapCombatSign.Success)
- { // 玩家死亡,失败,移除所有怪物的血条
- ClearEntities(false);
- if (sign is EMapCombatSign.FailedBoss)
- {
- _uiView?.SetBossFailed(true);
- }
- }
- _isMasking = true;
- }
- private void OnEndMask(int eventId, object args)
- {
- //var sign = (EMapCombatSign)args;
- _isMasking = false;
- }
- private void OnHpAdd(int eventId, object args)
- {
- PlayHpAdd((HpAddDto)args);
- }
- private void OnBossStart(int eventId, object args)
- {
- //var chapterId = (int)args;
- _uiView?.StartBossTime();
- }
- private void ClearEntities(bool includePlayer)
- {
- EntityBattleInfoView player = null;
- foreach (var entity in _entityViewsMap.Values)
- {
- if (!includePlayer && entity.Master.Entity.EntityType == EEntityType.Player)
- {
- player = entity;
- continue;
- }
- Context.Asset.Recycle(entity);
- }
- _entityViewsMap.Clear();
- _hpAddLastTimeMap.Clear();
- foreach(var timer in _hpAddTimers)
- {
- timer.Cancel();
- }
- _hpAddTimers.Clear();
- if (player != null)
- {
- _entityViewsMap.Add(player.Master.Entity.EntityId, player);
- }
- }
- private void PlayHpAdd(HpAddDto dto)
- {
- if (_uiView == null || _isMasking)
- return;
- RefreshEntity(dto.entityId);
- SaveHpAddTime(dto.entityId, out var delay);
- if (delay > 0)
- {
- ITimer timer = null;
- timer = Context.Time.AddDelayTimer(delay, () =>
- {
- _hpAddTimers.Remove(timer);
- LoadHpAddView(dto);
- });
- _hpAddTimers.Add(timer);
- }
- else
- {
- LoadHpAddView(dto);
- }
- }
- private void LoadHpAddView(HpAddDto dto)
- {
- var viewAsync = Context.Asset.LoadEntity<HpAddEntityView>(AddressableDefine.uihpadd, _uiView.CombatValRoot);
- viewAsync.On(_ =>
- {
- var hpAddView = viewAsync.Result;
- if (hpAddView == null)
- return;
- var localPoint = WorldToLocal(dto.position, _uiView.CombatValRoot);
- //var screenPoint = Context.VM.Camera.WorldToScreenPoint(dto.position);
- //RectTransformUtility.ScreenPointToLocalPointInRectangle(_uiView.CombatValRoot as RectTransform, screenPoint, UICamera, out var localPoint);
- hpAddView?.ShowValue(dto.hpValue, localPoint, dto.elementType, () =>
- {
- Context.Asset.Recycle(hpAddView);
- });
- });
- }
- /// <summary>
- /// 保存时间
- /// </summary>
- /// <param name="entityId"></param>
- /// <param name="delay">延迟播放时间,单位:毫秒</param>
- private void SaveHpAddTime(long entityId, out int delay)
- {
- delay = 0;
- var curTime = Context.Time.GetNowTime();
- if (_hpAddLastTimeMap.TryGetValue(entityId, out var lastTime))
- {
- const int interval = 200;
- var playTime = lastTime + interval;
- if (playTime > curTime)
- {
- lastTime = playTime;
- delay = (int)(playTime - curTime);
- }
- else
- {
- lastTime = curTime;
- }
- }
- else
- {
- lastTime = curTime;
- }
- _hpAddLastTimeMap[entityId] = lastTime;
- }
- private void LoadUIView()
- {
- var loadAsync = Context.Asset.LoadEntity<MainMapUIView>(AddressableDefine.mainmapui, Context.VM.UIRoot);
- _uiViewAsync = loadAsync;
- loadAsync.On(_ =>
- {
- _uiViewAsync = null;
- var uiView = loadAsync.Result;
- if (uiView == null)
- return;
- _uiView = uiView;
- uiView.RefreshChapter(_chapterId);
- });
- }
- #region 副本进度相关
- public void RefreshChapter(int chapterId)
- {
- if (_chapterId == chapterId) return;
- _chapterId = chapterId;
- _uiView?.RefreshChapter(chapterId);
- }
- #endregion
- }
- }
|