using FL.Battle; using FL.Data; using FL.Nodes.GameMain; using System.Collections.Generic; 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 IEntitiesContext { IMapAssetModule Asset { get; } ITimeModule Time { get; } TestMainMapVM VM { get; } } public class EntitiesComponent : Component, ILateUpdate { private PlayerEntityView _player; private Dictionary _partnerMap = new Dictionary(); /// /// 怪物的实例对象 /// private Dictionary _monsterMap = new Dictionary(); private TargetSelector _selector; private ITimer _selectorTimer; public override int Order => 0; protected override void OnEnable(object intent) { InitSelector(); EventSingle.Instance.AddListener(EventDefine.GameMainMapLoadEntities, OnLoadEntities); EventSingle.Instance.AddListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity); EventSingle.Instance.AddListener(EventDefine.GameMainMapFindTarget, OnFindTarget); EventSingle.Instance.AddListener(EventDefine.GameMainMapStartMask, OnStartMask); } protected override void OnDisable() { EventSingle.Instance.RemoveListener(EventDefine.GameMainMapLoadEntities, OnLoadEntities); EventSingle.Instance.RemoveListener(EventDefine.GameMainMapRemoveEntity, OnRemoveEntity); EventSingle.Instance.RemoveListener(EventDefine.GameMainMapFindTarget, OnFindTarget); EventSingle.Instance.RemoveListener(EventDefine.GameMainMapStartMask, OnStartMask); ClearSelector(); Context.VM.Camera.Target = null; Context.Asset.Recycle(_player); foreach (var partner in _partnerMap.Values) { Context.Asset.Recycle(partner); } _partnerMap.Clear(); foreach (var monster in _monsterMap.Values) { Context.Asset.Recycle(monster); } _monsterMap.Clear(); } protected override void OnDispose() { } void ILateUpdate.LateUpdate(int millisecond) { Context.VM.UpdateMapMoveTime(millisecond); Context.VM.Camera.OnLateUpdate(millisecond); } #region 事件监听 private void OnLoadEntities(int eventId, object args) { var dto = (LoadEntitiesDto)args; var asyncGroup = new AsyncGroup(); if (dto.player != null) { // 第一波怪物,玩家不存在时 var playerAsync = Context.Asset.LoadEntity("Player", Context.VM.PlayerRoot); playerAsync.On(_ => { var entityView = playerAsync.Result; if (entityView == null) { return; } entityView.Entity = dto.player; Context.VM.Camera.Target = entityView.GetComponent();// behaviour.transform; _player = entityView; _selector.Register(entityView); }); playerAsync.Join(asyncGroup); } else if (dto.isChapterChanged) { Context.VM.Reset(); _player.Reset(); foreach (var item in _partnerMap) { item.Value.Reset(); } } var partnerCount = dto.partners?.Length ?? 0; if (partnerCount > 0) { // 创建伙伴实例 for (var i = 0; i < partnerCount; i++) { var partner = dto.partners[i]; var table = PartnerTableRepo.Get(partner.TableId); var loadAsync = Context.Asset.LoadEntity(table.Model, Context.VM.PlayerRoot); loadAsync.On(_ => { var entityView = loadAsync.Result; if (entityView == null) { return; } entityView.Entity = partner; entityView.BodyMirror(); _partnerMap.Add(partner.EntityId, entityView); _selector.Register(entityView); }); loadAsync.Join(asyncGroup); } } var monsterCount = dto.monsters?.Length ?? 0; if (monsterCount > 0) { // 创建怪物实例 for (var i = 0; i < monsterCount; i++) { var monster = dto.monsters[i]; var table = MonsterTableRepo.Get(monster.TableId); var loadAsync = Context.Asset.LoadEntity(table.Model, Context.VM.EnemyRoot); loadAsync.On(_ => { var entityView = loadAsync.Result; if (entityView == null) { return; } entityView.Entity = monster; entityView.Entity = monster; _monsterMap.Add(monster.EntityId, entityView); _selector.Register(entityView); }); loadAsync.Join(asyncGroup); } } asyncGroup.On(_ => { //Entities加载完成,开始移动 if (dto.isPlayerMove) { var args = new MoveArgs { target = dto.battlePosition, speed = _player.Entity.Attr.MoveSpeed, callback = () => { // 玩家移动速度快,先到目标坐标 _player.State = EEntityState.Alert; _selector.Start(new FindTargetArgs() { entityId = _player.Entity.EntityId, entityType = EEntityType.Monster, range = 6, skillId = PlayerData.Instance.skillId }); if (dto.isChapterChanged) { Context.VM.SetFocusPosition(_player.Position); } } }; _player.State = EEntityState.Protected; _player.MoveTo(args); foreach (var item in _partnerMap) { var entityView = item.Value; var entity = entityView.Entity; var table = PartnerTableRepo.Get(entity.TableId); var tarPosition = dto.battlePosition; tarPosition += PlayerData.Instance.GetSwordOffset((int)table.Type - 1); var moveArgs = new MoveArgs { target = tarPosition, speed = entity.Attr.MoveSpeed, callback = () => { entityView.State = EEntityState.Alert; _selector.Start(new FindTargetArgs() { entityId = entity.EntityId, entityType = EEntityType.Monster, range = entity.Attr.AtkRange, skillId = table.Skill, }); } }; entityView.State = EEntityState.Protected; entityView.MoveTo(moveArgs); } } var monsterCount = dto.monsters?.Length ?? 0; for (var mIdx = 0; mIdx < monsterCount; mIdx++) { var entity = dto.monsters[mIdx]; //var monsterTable = MonsterTableRepo.Get(entity.TableId); var tarPosition = entity.TargetPosition; tarPosition.y += (-dto.monsterMoveDistance + entity.Attr.AtkRange + entity.Attr.Radius); var entityView = _monsterMap[entity.EntityId]; var args = new MoveArgs { target = tarPosition, speed = entity.Attr.MoveSpeed, delay = dto.monsterMoveDelay, callback = () => { entityView.State = EEntityState.Alert; _selector.Start(new FindTargetArgs() { entityId = entity.EntityId, entityType = EEntityType.Player, range = entity.Attr.AtkRange, skillId = MonsterTableRepo.Get(entity.TableId).Skill, }); } }; entityView.State = EEntityState.Protected; entityView.MoveTo(args); } }); asyncGroup.End(); } private void OnRemoveEntity(int eventId, object args) { var entityId = (int)args; if (_monsterMap.TryGetValue(entityId, out var entity)) { _monsterMap.Remove(entityId); _selector?.Unregister(entity); Context.Asset.Recycle(entity); return; } if (_partnerMap.TryGetValue(entityId, out var partner)) { _partnerMap.Remove(entityId); _selector?.Unregister(partner); Context.Asset.Recycle(partner); return; } if (entityId == _player?.Entity.EntityId) { Context.Asset.Recycle(_player); _selector?.Unregister(_player); _player = null; } } #endregion #region 目标选择 private void InitSelector() { if (_selector == null) { _selector = new TargetSelector(); } _selectorTimer = Context.Time.AddLooperTimer(100, _selector.Selects); } private void ClearSelector() { _selector?.Clear(); _selectorTimer?.Cancel(); _selectorTimer = null; } private void OnFindTarget(int eventId, object args) { var targetArgs = (FindTargetArgs)args; _selector?.Start(targetArgs); } #endregion #region 黑屏 private void OnStartMask(int eventId, object args) { var duration = 2; PlayerMoveToCenter(duration); Context.VM.ShowBlackMask(duration, () => { EventSingle.Instance.Notify(EventDefine.GameMainMapEndMask); }); } /// /// 玩家移动到屏幕中心 /// /// 单位:秒 private void PlayerMoveToCenter(float duration) { var centerPosition = Context.VM.Camera.TopCenterToWorldPosition(); var distance = centerPosition.y - _player.Position.y; var speed = distance / duration; var targetPosition = Context.VM.PlayerRoot.InverseTransformPoint(centerPosition); Log.Debug($"PlayerMoveToCenter Player World:{_player.Position} Local:{_player.LocalPosition} Center World:{centerPosition} Local:{targetPosition}"); var args = new MoveArgs { target = targetPosition, speed = speed, }; _player.State = EEntityState.Protected; _player.MoveTo(args); foreach (var item in _partnerMap) { var entityView = item.Value; var entity = entityView.Entity; var table = PartnerTableRepo.Get(entity.TableId); var tarPosition = targetPosition; tarPosition += PlayerData.Instance.GetSwordOffset((int)table.Type - 1); var moveArgs = new MoveArgs { target = tarPosition, speed = speed, }; entityView.State = EEntityState.Protected; entityView.MoveTo(moveArgs); } } #endregion } }