using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Config; using Godot; /// <summary> /// 房间预设处理类 /// </summary> public class RoomPreinstall : IDestroy { public bool IsDestroyed { get; private set; } /// <summary> /// 所属房间对象 /// </summary> public RoomInfo RoomInfo { get; } /// <summary> /// 绑定的预设数据 /// </summary> public RoomPreinstallInfo RoomPreinstallInfo { get; } /// <summary> /// 总波数 /// </summary> public int WaveCount => RoomPreinstallInfo.WaveList.Count; /// <summary> /// 波数和标记数据列表 /// </summary> public List<List<ActivityMark>> WaveList { get; } = new List<List<ActivityMark>>(); /// <summary> /// 是否正在执行生成波数操作 /// </summary> public bool IsRunWave { get; private set; } /// <summary> /// 是否执行到最后一波了 /// </summary> public bool IsLastWave => _currWaveIndex >= WaveList.Count; //是否运行过预处理 private bool _runPretreatment = false; //当前房间是否会刷新敌人 private bool _hsaEnemy = false; //当前波数索引 private int _currWaveIndex = 0; //执行生成标记的协程id private long _coroutineId = -1; public RoomPreinstall(RoomInfo roomInfo, RoomPreinstallInfo roomPreinstallInfo) { RoomInfo = roomInfo; RoomPreinstallInfo = roomPreinstallInfo; } /// <summary> /// 预处理操作 /// </summary> public void Pretreatment(SeedRandom random) { if (_runPretreatment) { return; } _runPretreatment = true; //确定房间内要生成写啥 foreach (var markInfos in RoomPreinstallInfo.WaveList) { var wave = new List<ActivityMark>(); WaveList.Add(wave); foreach (var markInfo in markInfos) { var mark = new ActivityMark(); if (markInfo.SpecialMarkType == SpecialMarkType.Normal) //普通标记 { MarkInfoItem markInfoItem; if (markInfo.MarkList.Count == 0) { continue; } else if (markInfo.MarkList.Count == 1) { markInfoItem = markInfo.MarkList[0]; } else { var tempArray = markInfo.MarkList.Select(item => item.Weight).ToArray(); var index = random.RandomWeight(tempArray); markInfoItem = markInfo.MarkList[index]; } mark.Id = markInfoItem.Id; mark.Attr = markInfoItem.Attr; mark.DerivedAttr = new Dictionary<string, string>(); mark.VerticalSpeed = markInfoItem.VerticalSpeed; mark.Altitude = markInfoItem.Altitude; mark.ActivityType = (ActivityType)ExcelConfig.ActivityObject_Map[markInfoItem.Id].Type; if (mark.ActivityType == ActivityType.Enemy) //敌人类型 { _hsaEnemy = true; if (!mark.Attr.TryGetValue("Face", out var face) || face == "0") //随机方向 { mark.DerivedAttr.Add("Face", random.RandomChoose( ((int)FaceDirection.Left).ToString(), ((int)FaceDirection.Right).ToString() ) ); } else //指定方向 { mark.DerivedAttr.Add("Face", face); } } } else if (markInfo.SpecialMarkType == SpecialMarkType.BirthPoint) //玩家出生标记 { } else { GD.PrintErr("暂未支持的类型: " + markInfo.SpecialMarkType); continue; } mark.DelayTime = markInfo.DelayTime; mark.MarkType = markInfo.SpecialMarkType; //随机刷新坐标 var pos = markInfo.Position.AsVector2(); var birthRect = markInfo.Size.AsVector2(); var tempPos = new Vector2( random.RandomRangeInt((int)(pos.X - birthRect.X / 2), (int)(pos.X + birthRect.X / 2)), random.RandomRangeInt((int)(pos.Y - birthRect.Y / 2), (int)(pos.Y + birthRect.Y / 2)) ); var offset = RoomInfo.GetOffsetPosition(); //var offset = RoomInfo.RoomSplit.RoomInfo.Position.AsVector2I(); mark.Position = RoomInfo.GetWorldPosition() + (tempPos - offset); wave.Add(mark); } //排序操作 wave.Sort((a, b) => (int)(a.DelayTime * 1000 - b.DelayTime * 1000)); } } /// <summary> /// 预处理后才可以调用, 返回是否会生成敌人 /// </summary> public bool HasEnemy() { return _hsaEnemy; } /// <summary> /// 地牢房间加载完成 /// </summary> public void OnReady() { _currWaveIndex = 0; if (WaveList.Count > 0) { var activityMarks = WaveList[0]; foreach (var activityMark in activityMarks) { if (activityMark.MarkType == SpecialMarkType.Normal) { var activityObject = CreateItem(activityMark); //初始化属性 InitAttr(activityObject, activityMark); activityObject.PutDown(GetDefaultLayer(activityMark)); } } } _currWaveIndex++; } /// <summary> /// 玩家进入房间, 开始执行生成物体 /// </summary> public void StartWave() { if (IsRunWave) { return; } IsRunWave = true; _currWaveIndex = 1; GD.Print("执行第一波"); _coroutineId = GameApplication.Instance.StartCoroutine(RunMark(WaveList[_currWaveIndex])); _currWaveIndex++; } public void NextWave() { GD.Print("执行下一波, 当前: " + _currWaveIndex); _coroutineId = GameApplication.Instance.StartCoroutine(RunMark(WaveList[_currWaveIndex])); _currWaveIndex++; } //执行实例化标记物体 private IEnumerator RunMark(List<ActivityMark> activityMarks) { var timer = 0d; for (var i = 0; i < activityMarks.Count;) { var activityMark = activityMarks[i]; if (timer >= activityMark.DelayTime) { if (activityMark.MarkType == SpecialMarkType.Normal) { var activityObject = CreateItem(activityMark); activityObject.VerticalSpeed = activityMark.VerticalSpeed; activityObject.Altitude = activityMark.Altitude; //初始化属性 InitAttr(activityObject, activityMark); //播放出生动画 activityObject.StartCoroutine(OnActivityObjectBirth(activityObject)); activityObject.PutDown(GetDefaultLayer(activityMark)); var effect1 = ResourceManager.LoadAndInstantiate<Effect1>(ResourcePath.prefab_effect_Effect1_tscn); effect1.Position = activityObject.Position + new Vector2(0, -activityMark.Altitude); effect1.AddToActivityRoot(RoomLayerEnum.YSortLayer); } i++; } else { timer += GameApplication.Instance.GetProcessDeltaTime(); yield return 0; } } _coroutineId = -1; } //生成 ActivityObject 时调用, 用于出生时的动画效果 private IEnumerator OnActivityObjectBirth(ActivityObject instance) { var a = 1.0f; instance.SetBlendColor(Colors.White); //禁用自定义行为 instance.EnableCustomBehavior = false; //禁用下坠 instance.EnableVerticalMotion = false; for (var i = 0; i < 10; i++) { instance.SetBlendSchedule(a); yield return 0; } while (a > 0) { instance.SetBlendSchedule(a); a -= 0.05f; yield return 0; } //启用自定义行为 instance.EnableCustomBehavior = true; //启用下坠 instance.EnableVerticalMotion = true; } /// <summary> /// 当前这一波是否执行完成 /// </summary> public bool IsCurrWaveOver() { return _coroutineId < 0 || GameApplication.Instance.IsCoroutineOver(_coroutineId); } //创建物体 private ActivityObject CreateItem(ActivityMark activityMark) { var activityObject = ActivityObject.Create(activityMark.Id); activityObject.Position = activityMark.Position; return activityObject; } //获取物体默认所在层级 private RoomLayerEnum GetDefaultLayer(ActivityMark activityMark) { if (activityMark.ActivityType == ActivityType.Player || activityMark.ActivityType == ActivityType.Enemy) { return RoomLayerEnum.YSortLayer; } return RoomLayerEnum.NormalLayer; } /// <summary> /// 获取房间内的玩家生成标记 /// </summary> public ActivityMark GetPlayerBirthMark() { if (WaveList.Count == 0) { return null; } var activityMarks = WaveList[0]; var activityMark = activityMarks.FirstOrDefault(mark => mark.MarkType == SpecialMarkType.BirthPoint); return activityMark; } public void Destroy() { if (IsDestroyed) { return; } IsDestroyed = true; if (_coroutineId >= 0) { GameApplication.Instance.StopCoroutine(_coroutineId); } WaveList.Clear(); } //初始化物体属性 private void InitAttr(ActivityObject activityObject, ActivityMark activityMark) { if (activityMark.ActivityType == ActivityType.Weapon) //武器类型 { var weapon = (Weapon)activityObject; if (activityMark.Attr.TryGetValue("CurrAmmon", out var currAmmon)) //当前弹夹弹药 { weapon.SetCurrAmmo(int.Parse(currAmmon)); } if (activityMark.Attr.TryGetValue("ResidueAmmo", out var residueAmmo)) //剩余弹药 { weapon.SetResidueAmmo(int.Parse(residueAmmo)); } } else if (activityMark.ActivityType == ActivityType.Enemy) //敌人类型 { var enemy = (Enemy)activityObject; if (activityMark.Attr.TryGetValue("Weapon", out var weaponId)) //使用的武器 { if (!string.IsNullOrEmpty(weaponId)) { var weapon = ActivityObject.Create<Weapon>(weaponId); enemy.PickUpWeapon(weapon); if (activityMark.Attr.TryGetValue("CurrAmmon", out var currAmmon)) //当前弹夹弹药 { weapon.SetCurrAmmo(int.Parse(currAmmon)); } if (activityMark.Attr.TryGetValue("ResidueAmmo", out var residueAmmo)) //剩余弹药 { weapon.SetResidueAmmo(int.Parse(residueAmmo)); } } } if (activityMark.DerivedAttr.TryGetValue("Face", out var face)) //脸朝向, 应该只有 -1 和 1 { var faceDir = int.Parse(face); enemy.Face = (FaceDirection)faceDir; } } } }