Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / preinstall / RoomPreinstall.cs
@小李xl 小李xl on 21 Nov 2023 14 KB 第二种敌人动画
  1.  
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Config;
  6. using Godot;
  7.  
  8. /// <summary>
  9. /// 房间预设处理类
  10. /// </summary>
  11. public class RoomPreinstall : IDestroy
  12. {
  13. public bool IsDestroyed { get; private set; }
  14.  
  15. /// <summary>
  16. /// 所属房间对象
  17. /// </summary>
  18. public RoomInfo RoomInfo { get; }
  19. /// <summary>
  20. /// 绑定的预设数据
  21. /// </summary>
  22. public RoomPreinstallInfo RoomPreinstallInfo { get; }
  23.  
  24. /// <summary>
  25. /// 总波数
  26. /// </summary>
  27. public int WaveCount => RoomPreinstallInfo.WaveList.Count;
  28.  
  29. /// <summary>
  30. /// 波数和标记数据列表
  31. /// </summary>
  32. public List<List<ActivityMark>> WaveList { get; } = new List<List<ActivityMark>>();
  33.  
  34. /// <summary>
  35. /// 是否正在执行生成波数操作
  36. /// </summary>
  37. public bool IsRunWave { get; private set; }
  38.  
  39. /// <summary>
  40. /// 是否执行到最后一波了
  41. /// </summary>
  42. public bool IsLastWave => _currWaveIndex >= WaveList.Count;
  43. //是否运行过预处理
  44. private bool _runPretreatment = false;
  45. //当前房间是否会刷新敌人
  46. private bool _hsaEnemy = false;
  47. //当前波数索引
  48. private int _currWaveIndex = 0;
  49. //执行生成标记的协程id
  50. private long _coroutineId = -1;
  51. //提前加载列表
  52. private List<PreloadData> _readyList;
  53.  
  54. private class PreloadData
  55. {
  56. /// <summary>
  57. /// 实例对象
  58. /// </summary>
  59. public ActivityObject ActivityObject;
  60. /// <summary>
  61. /// 所在层级
  62. /// </summary>
  63. public RoomLayerEnum Layer;
  64.  
  65. public PreloadData(ActivityObject activityObject, RoomLayerEnum layer)
  66. {
  67. ActivityObject = activityObject;
  68. Layer = layer;
  69. }
  70. }
  71.  
  72. public RoomPreinstall(RoomInfo roomInfo, RoomPreinstallInfo roomPreinstallInfo)
  73. {
  74. RoomInfo = roomInfo;
  75. RoomPreinstallInfo = roomPreinstallInfo;
  76. }
  77.  
  78. /// <summary>
  79. /// 预处理操作
  80. /// </summary>
  81. public void Pretreatment(SeedRandom random)
  82. {
  83. if (_runPretreatment)
  84. {
  85. return;
  86. }
  87.  
  88. _runPretreatment = true;
  89.  
  90. //确定房间内要生成写啥
  91. foreach (var markInfos in RoomPreinstallInfo.WaveList)
  92. {
  93. var wave = new List<ActivityMark>();
  94. WaveList.Add(wave);
  95. foreach (var markInfo in markInfos)
  96. {
  97. var mark = new ActivityMark();
  98. if (markInfo.SpecialMarkType == SpecialMarkType.Normal) //普通标记
  99. {
  100. MarkInfoItem markInfoItem;
  101. if (markInfo.MarkList.Count == 0)
  102. {
  103. continue;
  104. }
  105. else if (markInfo.MarkList.Count == 1)
  106. {
  107. markInfoItem = markInfo.MarkList[0];
  108. }
  109. else
  110. {
  111. var tempArray = markInfo.MarkList.Select(item => item.Weight).ToArray();
  112. var index = random.RandomWeight(tempArray);
  113. markInfoItem = markInfo.MarkList[index];
  114. }
  115.  
  116. mark.Id = markInfoItem.Id;
  117. mark.Attr = markInfoItem.Attr;
  118. mark.DerivedAttr = new Dictionary<string, string>();
  119. mark.VerticalSpeed = markInfoItem.VerticalSpeed;
  120. mark.Altitude = markInfoItem.Altitude;
  121. mark.ActivityType = (ActivityType)ExcelConfig.ActivityBase_Map[markInfoItem.Id].Type;
  122.  
  123. if (mark.ActivityType == ActivityType.Enemy) //敌人类型
  124. {
  125. _hsaEnemy = true;
  126. if (!mark.Attr.TryGetValue("Face", out var face) || face == "0") //随机方向
  127. {
  128. mark.DerivedAttr.Add("Face",
  129. random.RandomChoose(
  130. ((int)FaceDirection.Left).ToString(),
  131. ((int)FaceDirection.Right).ToString()
  132. )
  133. );
  134. }
  135. else //指定方向
  136. {
  137. mark.DerivedAttr.Add("Face", face);
  138. }
  139. }
  140. }
  141. else if (markInfo.SpecialMarkType == SpecialMarkType.BirthPoint) //玩家出生标记
  142. {
  143.  
  144. }
  145. else
  146. {
  147. Debug.LogError("暂未支持的类型: " + markInfo.SpecialMarkType);
  148. continue;
  149. }
  150.  
  151. mark.DelayTime = markInfo.DelayTime;
  152. mark.MarkType = markInfo.SpecialMarkType;
  153. //随机刷新坐标
  154. var pos = markInfo.Position.AsVector2();
  155. var birthRect = markInfo.Size.AsVector2();
  156. var tempPos = new Vector2(
  157. random.RandomRangeInt((int)(pos.X - birthRect.X / 2), (int)(pos.X + birthRect.X / 2)),
  158. random.RandomRangeInt((int)(pos.Y - birthRect.Y / 2), (int)(pos.Y + birthRect.Y / 2))
  159. );
  160. //var offset = RoomInfo.RoomSplit.RoomInfo.Position.AsVector2I();
  161. //mark.Position = RoomInfo.GetWorldPosition() + tempPos - offset;
  162. mark.Position = RoomInfo.ToGlobalPosition(tempPos);
  163. wave.Add(mark);
  164. }
  165.  
  166. //排序操作
  167. wave.Sort((a, b) => (int)(a.DelayTime * 1000 - b.DelayTime * 1000));
  168. }
  169. }
  170.  
  171. /// <summary>
  172. /// 预处理后才可以调用, 返回是否会生成敌人
  173. /// </summary>
  174. public bool HasEnemy()
  175. {
  176. return _hsaEnemy;
  177. }
  178. /// <summary>
  179. /// 地牢房间加载完成
  180. /// </summary>
  181. public void OnReady()
  182. {
  183. _currWaveIndex = 0;
  184. //加载提前生成的物体
  185. if (WaveList.Count > 0)
  186. {
  187. var activityMarks = WaveList[0];
  188. foreach (var activityMark in activityMarks)
  189. {
  190. if (activityMark.MarkType == SpecialMarkType.Normal)
  191. {
  192. var activityObject = CreateItem(activityMark);
  193. //初始化属性
  194. InitAttr(activityObject, activityMark);
  195. if (_readyList == null)
  196. {
  197. _readyList = new List<PreloadData>();
  198. }
  199. _readyList.Add(new PreloadData(activityObject, GetDefaultLayer(activityMark)));
  200. }
  201. }
  202. }
  203.  
  204. _currWaveIndex++;
  205. }
  206.  
  207. /// <summary>
  208. /// 玩家进入房间, 开始执行生成物体
  209. /// </summary>
  210. public void StartWave()
  211. {
  212. if (IsRunWave)
  213. {
  214. return;
  215. }
  216.  
  217. IsRunWave = true;
  218.  
  219. _currWaveIndex = 1;
  220. //判断房间内是否已经有敌人了
  221. var hasEnemy = false;
  222. if (_readyList != null && _readyList.Count > 0)
  223. {
  224. foreach (var preloadData in _readyList)
  225. {
  226. //有敌人
  227. if (!hasEnemy && preloadData.ActivityObject.CollisionWithMask(PhysicsLayer.Enemy))
  228. {
  229. hasEnemy = true;
  230. }
  231.  
  232. preloadData.ActivityObject.PutDown(preloadData.Layer);
  233. }
  234.  
  235. _readyList.Clear();
  236. _readyList = null;
  237. }
  238.  
  239. if (!hasEnemy)
  240. {
  241. hasEnemy = RoomInfo.AffiliationArea.ExistIncludeItem(
  242. activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy)
  243. );
  244. }
  245.  
  246. if (!hasEnemy) //没有敌人才能执行第1波
  247. {
  248. if (_currWaveIndex < WaveList.Count)
  249. {
  250. Debug.Log($"执行第{_currWaveIndex}波");
  251. _coroutineId = World.Current.StartCoroutine(RunMark(WaveList[_currWaveIndex]));
  252. _currWaveIndex++;
  253. }
  254. }
  255. }
  256.  
  257. /// <summary>
  258. /// 执行下一波
  259. /// </summary>
  260. public void NextWave()
  261. {
  262. if (!IsRunWave)
  263. {
  264. return;
  265. }
  266. Debug.Log($"执行第{_currWaveIndex}波");
  267. _coroutineId = World.Current.StartCoroutine(RunMark(WaveList[_currWaveIndex]));
  268. _currWaveIndex++;
  269. }
  270.  
  271. /// <summary>
  272. /// 结束生成标记
  273. /// </summary>
  274. public void OverWave()
  275. {
  276. IsRunWave = false;
  277. }
  278. //执行实例化标记物体
  279. private IEnumerator RunMark(List<ActivityMark> activityMarks)
  280. {
  281. var timer = 0d;
  282. for (var i = 0; i < activityMarks.Count;)
  283. {
  284. var activityMark = activityMarks[i];
  285. if (timer >= activityMark.DelayTime)
  286. {
  287. if (activityMark.MarkType == SpecialMarkType.Normal)
  288. {
  289. var activityObject = CreateItem(activityMark);
  290. //初始化属性
  291. InitAttr(activityObject, activityMark);
  292. //播放出生动画
  293. activityObject.StartCoroutine(OnActivityObjectBirth(activityObject));
  294. activityObject.PutDown(GetDefaultLayer(activityMark));
  295. activityObject.UpdateFall((float)GameApplication.Instance.GetProcessDeltaTime());
  296.  
  297. if (activityObject is Enemy enemy)
  298. {
  299. //出生调用
  300. enemy.OnBornFromMark();
  301. }
  302. var effect = ObjectManager.GetPoolItem<IEffect>(ResourcePath.prefab_effect_common_Effect1_tscn);
  303. var node = (Node2D)effect;
  304. node.Position = activityObject.Position + new Vector2(0, -activityMark.Altitude);
  305. node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  306. effect.PlayEffect();
  307. }
  308. i++;
  309. }
  310. else
  311. {
  312. timer += GameApplication.Instance.GetProcessDeltaTime();
  313. yield return 0;
  314. }
  315. }
  316.  
  317. _coroutineId = -1;
  318. }
  319.  
  320. //生成 ActivityObject 时调用, 用于出生时的动画效果
  321. private IEnumerator OnActivityObjectBirth(ActivityObject instance)
  322. {
  323. var a = 1.0f;
  324. instance.SetBlendColor(Colors.White);
  325. //禁用自定义行为
  326. instance.EnableCustomBehavior = false;
  327. //禁用下坠
  328. instance.EnableVerticalMotion = false;
  329.  
  330. instance.SetBlendSchedule(a);
  331. yield return new WaitForFixedProcess(10);
  332.  
  333. while (a > 0)
  334. {
  335. instance.SetBlendSchedule(a);
  336. a -= 0.05f;
  337. yield return 0;
  338. }
  339. instance.SetBlendSchedule(0);
  340.  
  341. //启用自定义行为
  342. instance.EnableCustomBehavior = true;
  343. //启用下坠
  344. instance.EnableVerticalMotion = true;
  345. }
  346.  
  347. /// <summary>
  348. /// 当前这一波是否执行完成
  349. /// </summary>
  350. public bool IsCurrWaveOver()
  351. {
  352. return _coroutineId < 0 || World.Current.IsCoroutineOver(_coroutineId);
  353. }
  354. //创建物体
  355. private ActivityObject CreateItem(ActivityMark activityMark)
  356. {
  357. var activityObject = ActivityObject.Create(activityMark.Id);
  358. activityObject.Position = activityMark.Position;
  359. activityObject.VerticalSpeed = activityMark.VerticalSpeed;
  360. activityObject.Altitude = activityMark.Altitude;
  361. return activityObject;
  362. }
  363.  
  364. //获取物体默认所在层级
  365. private RoomLayerEnum GetDefaultLayer(ActivityMark activityMark)
  366. {
  367. if (activityMark.ActivityType == ActivityType.Player || activityMark.ActivityType == ActivityType.Enemy)
  368. {
  369. return RoomLayerEnum.YSortLayer;
  370. }
  371.  
  372. return RoomLayerEnum.NormalLayer;
  373. }
  374. /// <summary>
  375. /// 获取房间内的玩家生成标记
  376. /// </summary>
  377. public ActivityMark GetPlayerBirthMark()
  378. {
  379. if (WaveList.Count == 0)
  380. {
  381. return null;
  382. }
  383.  
  384. var activityMarks = WaveList[0];
  385. var activityMark = activityMarks.FirstOrDefault(mark => mark.MarkType == SpecialMarkType.BirthPoint);
  386. return activityMark;
  387. }
  388.  
  389. public void Destroy()
  390. {
  391. if (IsDestroyed)
  392. {
  393. return;
  394. }
  395.  
  396. IsDestroyed = true;
  397. if (_coroutineId >= 0)
  398. {
  399. World.Current.StopCoroutine(_coroutineId);
  400. }
  401.  
  402. WaveList.Clear();
  403. if (_readyList != null)
  404. {
  405. foreach (var preloadData in _readyList)
  406. {
  407. preloadData.ActivityObject.Destroy();
  408. }
  409.  
  410. _readyList.Clear();
  411. }
  412. }
  413.  
  414. //初始化物体属性
  415. private void InitAttr(ActivityObject activityObject, ActivityMark activityMark)
  416. {
  417. if (activityMark.ActivityType == ActivityType.Weapon) //武器类型
  418. {
  419. var weapon = (Weapon)activityObject;
  420. if (activityMark.Attr.TryGetValue("CurrAmmon", out var currAmmon)) //当前弹夹弹药
  421. {
  422. weapon.SetCurrAmmo(int.Parse(currAmmon));
  423. }
  424. if (activityMark.Attr.TryGetValue("ResidueAmmo", out var residueAmmo)) //剩余弹药
  425. {
  426. weapon.SetResidueAmmo(int.Parse(residueAmmo));
  427. }
  428. }
  429. else if (activityMark.ActivityType == ActivityType.Enemy) //敌人类型
  430. {
  431. var role = (Role)activityObject;
  432. if (role is Enemy enemy && activityMark.Attr.TryGetValue("Weapon", out var weaponId)) //使用的武器
  433. {
  434. if (!string.IsNullOrEmpty(weaponId))
  435. {
  436. var weapon = ActivityObject.Create<Weapon>(weaponId);
  437. enemy.PickUpWeapon(weapon);
  438. if (activityMark.Attr.TryGetValue("CurrAmmon", out var currAmmon)) //当前弹夹弹药
  439. {
  440. weapon.SetCurrAmmo(int.Parse(currAmmon));
  441. }
  442. if (activityMark.Attr.TryGetValue("ResidueAmmo", out var residueAmmo)) //剩余弹药
  443. {
  444. weapon.SetResidueAmmo(int.Parse(residueAmmo));
  445. }
  446. }
  447. }
  448.  
  449. if (activityMark.DerivedAttr.TryGetValue("Face", out var face)) //脸朝向, 应该只有 -1 和 1
  450. {
  451. var faceDir = int.Parse(face);
  452. role.Face = (FaceDirection)faceDir;
  453. }
  454. }
  455. }
  456. }