diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json index 2d774c3..e2c67d6 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json @@ -1 +1 @@ -[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":-11,"Y":-85},"Size":{"X":110,"Y":27},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"}}]},{"Position":{"X":64,"Y":27},"Size":{"X":94,"Y":60},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"}},{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"}}]}],[{"Position":{"X":-26,"Y":-13},"Size":{"X":76,"Y":10},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":200,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"}},{"Id":"enemy0001","Weight":50,"Attr":{"Weapon":"weapon0006","CurrAmmon":"20","ResidueAmmo":"20"}}]}]]},{"Name":"test2","Weight":200,"Remark":"","WaveList":[[{"Position":{"X":24,"Y":-46},"Size":{"X":16,"Y":94},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5000","Weight":30,"Attr":null},{"Id":"prop0005","Weight":90,"Attr":null}]}],[{"Position":{"X":67,"Y":27},"Size":{"X":85,"Y":48},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"enemy0001","Weight":60,"Attr":{"Weapon":"weapon0001","CurrAmmon":"30","ResidueAmmo":"30"}},{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":"weapon0003","CurrAmmon":"12","ResidueAmmo":"12"}}]}]]}] \ No newline at end of file +[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":-11,"Y":-85},"Size":{"X":110,"Y":27},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":64,"Y":27},"Size":{"X":94,"Y":60},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0},{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":-26,"Y":-13},"Size":{"X":76,"Y":10},"SpecialMarkType":0,"DelayTime":2.5,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0},{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":"weapon0005","CurrAmmon":"10","ResidueAmmo":"10"},"Altitude":0,"VerticalSpeed":0}]},{"Position":{"X":25,"Y":-40},"Size":{"X":16,"Y":92},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":"weapon0006","CurrAmmon":"20","ResidueAmmo":"20"},"Altitude":0,"VerticalSpeed":0}]},{"Position":{"X":82,"Y":27},"Size":{"X":64,"Y":45},"SpecialMarkType":0,"DelayTime":3.5,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":97,"Y":-132},"Size":{"X":31,"Y":60},"SpecialMarkType":0,"DelayTime":5,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":null},"Altitude":0,"VerticalSpeed":0}]}],[{"Position":{"X":32,"Y":35},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":"weapon0005","CurrAmmon":"10","ResidueAmmo":"10"},"Altitude":0,"VerticalSpeed":0}]},{"Position":{"X":86,"Y":-113},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":3,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":null},"Altitude":0,"VerticalSpeed":0}]},{"Position":{"X":-56,"Y":-145},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":4,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_preinstall.json index 0637a08..70a6dd1 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_preinstall.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_preinstall.json @@ -1 +1 @@ -[] \ No newline at end of file +[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[],[{"Position":{"X":39,"Y":-36},"Size":{"X":86,"Y":90},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":"weapon0005","CurrAmmon":"10","ResidueAmmo":"10"}},{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":"weapon0003","CurrAmmon":"12","ResidueAmmo":"12"}}]},{"Position":{"X":-58,"Y":62},"Size":{"X":103,"Y":73},"SpecialMarkType":0,"DelayTime":3,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Weapon":"weapon0006","CurrAmmon":"20","ResidueAmmo":"20"}}]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_roomInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_roomInfo.json index ed74cc0..1cdb937 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_roomInfo.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room2/Room2_roomInfo.json @@ -1 +1 @@ -{"Position":{"X":-12,"Y":-8},"Size":{"X":22,"Y":17},"DoorAreaInfos":[{"Direction":3,"Start":0,"End":320},{"Direction":0,"Start":0,"End":240},{"Direction":2,"Start":0,"End":320},{"Direction":1,"Start":0,"End":240}],"GroupName":"TestGroup1","RoomType":0,"RoomName":"Room2","Weight":100,"Remark":""} \ No newline at end of file +{"Position":{"X":-12,"Y":-8},"Size":{"X":22,"Y":17},"DoorAreaInfos":[],"GroupName":"TestGroup1","RoomType":0,"RoomName":"Room2","Weight":100,"Remark":""} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Start1_preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Start1_preinstall.json index 362fdb1..78ec481 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Start1_preinstall.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Start1_preinstall.json @@ -1 +1 @@ -[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":137,"Y":137},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]}]]}] \ No newline at end of file +[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":137,"Y":137},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]}],[{"Position":{"X":135,"Y":114},"Size":{"X":179,"Y":90},"SpecialMarkType":0,"DelayTime":2,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs index 4bcc34f..5e747d7 100644 --- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs +++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs @@ -1417,7 +1417,12 @@ { ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId); } - + + public bool IsCoroutineOver(long coroutineId) + { + return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId); + } + public void StopAllCoroutine() { ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList); diff --git a/DungeonShooting_Godot/src/framework/coroutine/ICoroutine.cs b/DungeonShooting_Godot/src/framework/coroutine/ICoroutine.cs index 4f57206..d5fe772 100644 --- a/DungeonShooting_Godot/src/framework/coroutine/ICoroutine.cs +++ b/DungeonShooting_Godot/src/framework/coroutine/ICoroutine.cs @@ -17,6 +17,11 @@ public void StopCoroutine(long coroutineId); /// + /// 根据协程 id 判断该协程是否结束 + /// + public bool IsCoroutineOver(long coroutineId); + + /// /// 停止所有协程 /// public void StopAllCoroutine(); diff --git a/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs b/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs index 1d66289..5fd2b36 100644 --- a/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs +++ b/DungeonShooting_Godot/src/framework/coroutine/ProxyCoroutineHandler.cs @@ -1,4 +1,5 @@  +using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; @@ -17,111 +18,118 @@ var pairs = coroutineList.ToArray(); for (var i = 0; i < pairs.Length; i++) { - var item = pairs[i]; - var canNext = true; + try + { + var item = pairs[i]; + var canNext = true; - if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForSeconds) //等待秒数 - { - if (!item.WaitForSeconds.NextStep(delta)) + if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForSeconds) //等待秒数 { - canNext = false; - } - else - { - item.WaitState = CoroutineData.WaitTypeEnum.None; - item.WaitForSeconds = null; - } - } - else if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForFixedProcess) //等待帧数 - { - if (!item.WaitForFixedProcess.NextStep()) - { - canNext = false; - } - else - { - item.WaitState = CoroutineData.WaitTypeEnum.None; - item.WaitForFixedProcess = null; - } - } - else if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForTask) //等待Task - { - if (!item.WaitTask.IsCompleted) - { - canNext = false; - } - else - { - item.WaitState = CoroutineData.WaitTypeEnum.None; - item.WaitTask = null; - } - } - else if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForSignalAwaiter) //等待信号 - { - if (!item.WaitSignalAwaiter.IsCompleted) - { - canNext = false; - } - else - { - item.WaitState = CoroutineData.WaitTypeEnum.None; - item.WaitSignalAwaiter = null; - } - } - - if (canNext) - { - if (item.Enumerator.MoveNext()) - { - var next = item.Enumerator.Current; - if (next is IEnumerable enumerable) //嵌套协程 + if (!item.WaitForSeconds.NextStep(delta)) { - if (item.EnumeratorStack == null) - { - item.EnumeratorStack = new Stack(); - } - - item.EnumeratorStack.Push(item.Enumerator); - item.Enumerator = enumerable.GetEnumerator(); - } - else if (next is IEnumerator enumerator) //嵌套协程 - { - if (item.EnumeratorStack == null) - { - item.EnumeratorStack = new Stack(); - } - - item.EnumeratorStack.Push(item.Enumerator); - item.Enumerator = enumerator; - } - else if (next is WaitForSeconds seconds) //等待秒数 - { - item.WaitFor(seconds); - } - else if (next is WaitForFixedProcess process) //等待帧数 - { - item.WaitFor(process); - } - else if (next is Task task) //Task对象 - { - item.WaitFor(task); - } - else if (next is SignalAwaiter awaiter) //等待信号 - { - item.WaitFor(awaiter); - } - } - else - { - if (item.EnumeratorStack == null || item.EnumeratorStack.Count == 0) - { - ProxyStopCoroutine(ref coroutineList, item.Id); + canNext = false; } else { - item.Enumerator = item.EnumeratorStack.Pop(); + item.WaitState = CoroutineData.WaitTypeEnum.None; + item.WaitForSeconds = null; } } + else if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForFixedProcess) //等待帧数 + { + if (!item.WaitForFixedProcess.NextStep()) + { + canNext = false; + } + else + { + item.WaitState = CoroutineData.WaitTypeEnum.None; + item.WaitForFixedProcess = null; + } + } + else if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForTask) //等待Task + { + if (!item.WaitTask.IsCompleted) + { + canNext = false; + } + else + { + item.WaitState = CoroutineData.WaitTypeEnum.None; + item.WaitTask = null; + } + } + else if (item.WaitState == CoroutineData.WaitTypeEnum.WaitForSignalAwaiter) //等待信号 + { + if (!item.WaitSignalAwaiter.IsCompleted) + { + canNext = false; + } + else + { + item.WaitState = CoroutineData.WaitTypeEnum.None; + item.WaitSignalAwaiter = null; + } + } + + if (canNext) + { + if (item.Enumerator.MoveNext()) + { + var next = item.Enumerator.Current; + if (next is IEnumerable enumerable) //嵌套协程 + { + if (item.EnumeratorStack == null) + { + item.EnumeratorStack = new Stack(); + } + + item.EnumeratorStack.Push(item.Enumerator); + item.Enumerator = enumerable.GetEnumerator(); + } + else if (next is IEnumerator enumerator) //嵌套协程 + { + if (item.EnumeratorStack == null) + { + item.EnumeratorStack = new Stack(); + } + + item.EnumeratorStack.Push(item.Enumerator); + item.Enumerator = enumerator; + } + else if (next is WaitForSeconds seconds) //等待秒数 + { + item.WaitFor(seconds); + } + else if (next is WaitForFixedProcess process) //等待帧数 + { + item.WaitFor(process); + } + else if (next is Task task) //Task对象 + { + item.WaitFor(task); + } + else if (next is SignalAwaiter awaiter) //等待信号 + { + item.WaitFor(awaiter); + } + } + else + { + if (item.EnumeratorStack == null || item.EnumeratorStack.Count == 0) + { + ProxyStopCoroutine(ref coroutineList, item.Id); + } + else + { + item.Enumerator = item.EnumeratorStack.Pop(); + } + } + } + } + catch (Exception e) + { + GD.PrintErr("执行协程发生异常: \n" + e); } } } @@ -159,6 +167,26 @@ } } } + + /// + /// 代理协程, 根据 id 返回指定协程是否结束 + /// + public static bool ProxyIsCoroutineOver(ref List coroutineList, long coroutineId) + { + if (coroutineList != null) + { + for (var i = 0; i < coroutineList.Count; i++) + { + var item = coroutineList[i]; + if (item.Id == coroutineId) + { + return false; + } + } + } + + return true; + } /// /// 代理协程, 停止所有协程 diff --git a/DungeonShooting_Godot/src/framework/map/preinstall/ActivityMark.cs b/DungeonShooting_Godot/src/framework/map/preinstall/ActivityMark.cs index b4c72cf..5c1f35d 100644 --- a/DungeonShooting_Godot/src/framework/map/preinstall/ActivityMark.cs +++ b/DungeonShooting_Godot/src/framework/map/preinstall/ActivityMark.cs @@ -28,4 +28,21 @@ /// 延时时间, 单位: 秒 /// public float DelayTime { get; set; } + + /// + /// 物体初始海拔高度 + /// + public int Altitude = 8; + + /// + /// 物体初始纵轴速度 + /// + public float VerticalSpeed = 0; + + /// + /// 物体类型 + /// + public ActivityType ActivityType { get; set; } + + } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs index 4a98867..54b2a80 100644 --- a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs +++ b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs @@ -1,8 +1,10 @@  using System; +using System.Collections; using System.Collections.Generic; using System.Linq; +using Config; using Godot; /// @@ -32,7 +34,24 @@ /// public List> WaveList { get; } = new List>(); + /// + /// 是否正在执行生成波数操作 + /// + public bool IsRunWave { get; private set; } + + /// + /// 是否执行到最后一波了 + /// + 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) { @@ -80,6 +99,13 @@ mark.Id = markInfoItem.Id; mark.Attr = markInfoItem.Attr; + mark.VerticalSpeed = markInfoItem.VerticalSpeed; + mark.Altitude = markInfoItem.Altitude; + mark.ActivityType = (ActivityType)ExcelConfig.ActivityObject_Map[markInfoItem.Id].Type; + if (mark.ActivityType == ActivityType.Enemy) + { + _hsaEnemy = true; + } } else if (markInfo.SpecialMarkType == SpecialMarkType.BirthPoint) //玩家出生标记 { @@ -103,7 +129,6 @@ var offset = RoomInfo.GetOffsetPosition(); //var offset = RoomInfo.RoomSplit.RoomInfo.Position.AsVector2I(); mark.Position = RoomInfo.GetWorldPosition() + (tempPos - offset); - wave.Add(mark); } @@ -113,6 +138,155 @@ } /// + /// 预处理后才可以调用, 返回是否会生成敌人 + /// + public bool HasEnemy() + { + return _hsaEnemy; + } + + /// + /// 地牢房间加载完成 + /// + 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++; + } + + /// + /// 玩家进入房间, 开始执行生成物体 + /// + 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 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(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; + } + + /// + /// 当前这一波是否执行完成 + /// + 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; + } + + /// /// 获取房间内的玩家生成标记 /// public ActivityMark GetPlayerBirthMark() @@ -135,6 +309,48 @@ } 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(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)); + } + } + } + } + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs index 378d537..a486132 100644 --- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs @@ -179,12 +179,6 @@ RoomPreinstall.Destroy(); RoomPreinstall = null; } - - // foreach (var activityMark in ActivityMarks) - // { - // activityMark.QueueFree(); - // } - // ActivityMarks.Clear(); if (StaticImageCanvas != null) { @@ -193,43 +187,44 @@ } /// - /// 房间准备好了, 准备刷敌人, 并且关闭所有门, + /// 加载地牢完成 + /// + public void OnReady() + { + //提前加载波 + RoomPreinstall.OnReady(); + } + + /// + /// 玩家第一次进入房间, 房间准备好了, 准备刷敌人, 并且关闭所有
/// 当清完每一波刷新的敌人后即可开门 ///
- public void BeReady() + public void OnFirstEnter() { - // //没有标记, 啥都不要做 - // if (ActivityMarks.Count == 0) - // { - // _beReady = true; - // IsSeclusion = false; - // return; - // } - // IsSeclusion = true; - // _waveStart = false; - // - // if (!_beReady) - // { - // _beReady = true; - // //按照 WaveNumber 排序 - // ActivityMarks.Sort((x, y) => - // { - // return x.WaveNumber - y.WaveNumber; - // }); - // } - // - // //不是初始房间才能关门 - // if (RoomSplit.RoomInfo.RoomType != DungeonRoomType.Inlet) - // { - // //关门 - // foreach (var doorInfo in Doors) - // { - // doorInfo.Door.CloseDoor(); - // } - // } - // - // //执行第一波生成 - // NextWave(); + if (RoomPreinstall.IsRunWave) + { + return; + } + //没有额外标记, 啥都不要做 + if (RoomPreinstall.WaveCount <= 1) + { + IsSeclusion = false; + return; + } + IsSeclusion = true; + + //会刷新敌人才要关门 + if (RoomPreinstall.HasEnemy()) + { + //关门 + foreach (var doorInfo in Doors) + { + doorInfo.Door.CloseDoor(); + } + } + + //执行第一波生成 + RoomPreinstall.StartWave(); } /// @@ -237,23 +232,22 @@ /// public void OnClearRoom() { - // if (_currWaveIndex >= ActivityMarks.Count) //所有 mark 都走完了 - // { - // IsSeclusion = false; - // _currActivityMarks.Clear(); - // //开门 - // if (RoomSplit.RoomInfo.RoomType != DungeonRoomType.Inlet) - // { - // foreach (var doorInfo in Doors) - // { - // doorInfo.Door.OpenDoor(); - // } - // } - // } - // else //执行下一波 - // { - // NextWave(); - // } + if (RoomPreinstall.IsLastWave) //所有 mark 都走完了 + { + IsSeclusion = false; + //开门 + if (RoomPreinstall.HasEnemy()) + { + foreach (var doorInfo in Doors) + { + doorInfo.Door.OpenDoor(); + } + } + } + else //执行下一波 + { + NextWave(); + } } /// @@ -261,15 +255,7 @@ /// public bool IsCurrWaveOver() { - // for (var i = 0; i < _currActivityMarks.Count; i++) - // { - // if (!_currActivityMarks[i].IsOver()) - // { - // return false; - // } - // } - - return true; + return RoomPreinstall.IsCurrWaveOver(); } /// @@ -277,29 +263,6 @@ /// private void NextWave() { - // if (!_waveStart) - // { - // _waveStart = true; - // _currWaveIndex = 0; - // _currWaveNumber = ActivityMarks[0].WaveNumber; - // } - // GD.Print("执行下一波, 当前: " + _currWaveNumber); - // - // _currActivityMarks.Clear(); - // //根据标记生成对象 - // for (; _currWaveIndex < ActivityMarks.Count; _currWaveIndex++) - // { - // var mark = ActivityMarks[_currWaveIndex]; - // if (mark.WaveNumber != _currWaveNumber) //当前这波已经执行完成了 - // { - // _currWaveNumber = mark.WaveNumber; - // break; - // } - // else //生成操作 - // { - // mark.BeReady(this); - // _currActivityMarks.Add(mark); - // } - // } + RoomPreinstall.NextWave(); } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/serialize/MarkInfoItem.cs b/DungeonShooting_Godot/src/framework/map/serialize/MarkInfoItem.cs index 60a46c2..6e38c93 100644 --- a/DungeonShooting_Godot/src/framework/map/serialize/MarkInfoItem.cs +++ b/DungeonShooting_Godot/src/framework/map/serialize/MarkInfoItem.cs @@ -24,6 +24,18 @@ /// [JsonInclude] public Dictionary Attr; + + /// + /// 物体初始海拔高度 + /// + [JsonInclude] + public int Altitude; + + /// + /// 物体初始纵轴速度 + /// + [JsonInclude] + public float VerticalSpeed; /// /// 所属标记类型 diff --git a/DungeonShooting_Godot/src/framework/ui/UiBase.cs b/DungeonShooting_Godot/src/framework/ui/UiBase.cs index d0290b2..34b1c6a 100644 --- a/DungeonShooting_Godot/src/framework/ui/UiBase.cs +++ b/DungeonShooting_Godot/src/framework/ui/UiBase.cs @@ -351,6 +351,11 @@ ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId); } + public bool IsCoroutineOver(long coroutineId) + { + return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId); + } + public void StopAllCoroutine() { ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList); diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs index 693694c..eedb29b 100644 --- a/DungeonShooting_Godot/src/game/GameApplication.cs +++ b/DungeonShooting_Godot/src/game/GameApplication.cs @@ -201,7 +201,12 @@ { ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId); } - + + public bool IsCoroutineOver(long coroutineId) + { + return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId); + } + public void StopAllCoroutine() { ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList); diff --git a/DungeonShooting_Godot/src/game/activity/role/Player.cs b/DungeonShooting_Godot/src/game/activity/role/Player.cs index a34bf2b..b8b09eb 100644 --- a/DungeonShooting_Godot/src/game/activity/role/Player.cs +++ b/DungeonShooting_Godot/src/game/activity/role/Player.cs @@ -36,13 +36,13 @@ Shield = 0; // debug用 - RoleState.Acceleration = 3000; - RoleState.Friction = 3000; - RoleState.MoveSpeed = 500; - CollisionLayer = 0; - CollisionMask = 0; - GameCamera.Main.Zoom = new Vector2(.75f, 0.75f); - //GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f); + // RoleState.Acceleration = 3000; + // RoleState.Friction = 3000; + // RoleState.MoveSpeed = 500; + // CollisionLayer = 0; + // CollisionMask = 0; + // GameCamera.Main.Zoom = new Vector2(.75f, 0.75f); + // //GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f); } protected override void Process(float delta) diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs index 7f1e5a5..ab7680e 100644 --- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs +++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs @@ -68,7 +68,7 @@ GameApplication.Instance.StartCoroutine(RunExitDungeonCoroutine(finish)); } - public override void _PhysicsProcess(double delta) + public override void _Process(double delta) { if (IsInDungeon) { @@ -79,13 +79,8 @@ //检查房间内的敌人存活状况 OnCheckEnemy(); } - } - } - - public override void _Process(double delta) - { - if (IsInDungeon) - { + + //更新敌人视野 UpdateEnemiesView(); if (GameApplication.Instance.Debug) { @@ -146,6 +141,9 @@ player.Name = "Player"; player.PutDown(RoomLayerEnum.YSortLayer); Player.SetCurrentPlayer(player); + + //地牢加载即将完成 + _dungeonGenerator.EachRoom(info => info.OnReady()); //玩家手上添加武器 //player.PickUpWeapon(ActivityObject.Create(ActivityObject.Ids.Id_weapon0001)); @@ -410,7 +408,7 @@ private void OnPlayerFirstEnterRoom(object o) { var room = (RoomInfo)o; - room.BeReady(); + room.OnFirstEnter(); //如果关门了, 那么房间外的敌人就会丢失目标 if (room.IsSeclusion) { diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs index 4548f98..8ae4673 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs @@ -180,13 +180,23 @@ EditorWindowManager.ShowSelectObject(ActivityType.None, OnSelectObject, this); } - //选中物体回调 + //选中物体回调, 创建标记数据 private void OnSelectObject(ExcelConfig.ActivityObject activityObject) { + //初始值 + + //初始高度 + var altitude = 0; + if (activityObject.Type == (int)ActivityType.Weapon || activityObject.Type == (int)ActivityType.Prop) + { + altitude = 8; + } + _grid.Add(new MarkInfoItem() { Id = activityObject.Id, - Weight = 100 + Weight = 100, + Altitude = altitude }); } } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MarkObjectCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MarkObjectCell.cs index b64ec05..b9f7adb 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MarkObjectCell.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MarkObjectCell.cs @@ -9,8 +9,12 @@ //是否展开 private bool _isExpand = false; private MapEditorCreateMark.ExpandPanel _expandPanel; + //自定义额外属性 private List _attributeBases; private ExcelConfig.ActivityObject _activityObject; + + private MapEditorCreateMark.NumberBar _altitude; + private MapEditorCreateMark.NumberBar _vSpeed; public override void OnInit() { @@ -21,9 +25,8 @@ public override void OnSetData(MarkInfoItem data) { //记得判断随机对象, 后面再做 - - _activityObject = ExcelConfig.ActivityObject_Map[data.Id]; + //图标 if (string.IsNullOrEmpty(_activityObject.Icon)) { CellNode.L_VBoxContainer.L_HBoxContainer.L_Icon.Instance.Visible = false; @@ -39,16 +42,9 @@ CellNode.L_VBoxContainer.L_HBoxContainer.L_NameLabel.Instance.Text = _activityObject.Name; //物体类型 CellNode.L_VBoxContainer.L_HBoxContainer.L_TypeLabel.Instance.Text = NameManager.GetActivityTypeName(_activityObject.Type); + //权重 + CellNode.L_VBoxContainer.L_HBoxContainer.L_WeightEdit.Instance.Value = data.Weight; - // 包含额外属性 - if (_activityObject.Type == 5 || _activityObject.Type == 4) - { - if (_expandPanel == null) - { - CreateExpandPanel(_activityObject, data); - } - } - if (data.SpecialMarkType == SpecialMarkType.BirthPoint) //出生标记 { CellNode.L_VBoxContainer.L_HBoxContainer.L_CenterContainer.L_DeleteButton.Instance.Visible = false; @@ -56,8 +52,18 @@ } else //普通标记 { + // 包含额外属性 + if (_expandPanel == null) + { + CreateExpandPanel(_activityObject, data); + } CellNode.L_VBoxContainer.L_HBoxContainer.L_CenterContainer.L_DeleteButton.Instance.Visible = true; CellNode.L_VBoxContainer.L_HBoxContainer.L_WeightEdit.Instance.Visible = true; + + //海拔高度 + _altitude.L_NumInput.Instance.Value = data.Altitude; + //纵轴速度 + _vSpeed.L_NumInput.Instance.Value = data.VerticalSpeed; } } @@ -69,6 +75,8 @@ _attributeBases = null; _expandPanel.QueueFree(); _expandPanel = null; + _altitude = null; + _vSpeed = null; } SetExpandState(false); @@ -80,23 +88,47 @@ public MarkInfoItem GetMarkInfoItem() { var markInfoItem = Data; - if (_activityObject.Type == 5 || _activityObject.Type == 4) + + //额外属性 + if (_attributeBases != null) { - markInfoItem.Attr = new Dictionary(); + markInfoItem.Attr = null; foreach (var attributeBase in _attributeBases) { if (attributeBase.Visible) { + if (attributeBase.AttrName == "VSpeed" || attributeBase.AttrName == "Altitude") //不能是公共属性 + { + continue; + } + + if (markInfoItem.Attr == null) + { + markInfoItem.Attr = new Dictionary(); + } markInfoItem.Attr.Add(attributeBase.AttrName, attributeBase.GetAttributeValue()); } } } + if (Data.SpecialMarkType == SpecialMarkType.Normal) { + //权重 markInfoItem.Weight = (int)CellNode.L_VBoxContainer.L_HBoxContainer.L_WeightEdit.Instance.Value; } + //海拔高度 + if (_altitude != null && _altitude.Instance.Visible) + { + markInfoItem.Altitude = (int)_altitude.L_NumInput.Instance.Value; + } + //纵轴速度 + if (_vSpeed != null && _vSpeed.Instance.Visible)//海拔高度 + { + markInfoItem.VerticalSpeed = (float)_vSpeed.L_NumInput.Instance.Value; + } + return markInfoItem; } @@ -144,8 +176,20 @@ _expandPanel = CellNode.UiPanel.S_ExpandPanel.Clone(); _expandPanel.Instance.Visible = _isExpand; CellNode.L_VBoxContainer.AddChild(_expandPanel); - - if (activityObject.Type == 5) //武器类型 + + //公有类型 + _altitude = CellNode.UiPanel.CreateNumberBar("Altitude", "初始纵轴高度:"); + _vSpeed = CellNode.UiPanel.CreateNumberBar("VSpeed", "初始纵轴速度:"); + _altitude.L_NumInput.Instance.MaxValue = 128; + _altitude.L_NumInput.Instance.MinValue = 0; + _altitude.L_NumInput.Instance.Step = 1; + _vSpeed.L_NumInput.Instance.MaxValue = 1000; + _vSpeed.L_NumInput.Instance.MinValue = -1000; + _vSpeed.L_NumInput.Instance.Step = 0.1; + _expandPanel.L_ExpandGrid.AddChild(_altitude); + _expandPanel.L_ExpandGrid.AddChild(_vSpeed); + + if (activityObject.Type == (int)ActivityType.Weapon) //武器类型 { var numberBar = CellNode.UiPanel.CreateNumberBar("CurrAmmon", "弹夹弹药量:"); var numberBar2 = CellNode.UiPanel.CreateNumberBar("ResidueAmmo", "剩余弹药量:"); @@ -185,7 +229,7 @@ } } } - else if (activityObject.Type == 4) //敌人 + else if (activityObject.Type == (int)ActivityType.Enemy) //敌人 { var weaponBar = CellNode.UiPanel.CreateObjectBar("Weapon", "携带武器:", ActivityType.Weapon); var numberBar2 = CellNode.UiPanel.CreateNumberBar("CurrAmmon", "弹夹弹药量:");