Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / image / RoomStaticSprite.cs
@小李xl 小李xl on 7 Dec 2023 4 KB 更新开发日志
  1.  
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// RoomInfo 中用于存放静态Sprite的功能类
  7. /// </summary>
  8. public partial class RoomStaticSprite : Node2D, IDestroy
  9. {
  10. public bool IsDestroyed { get; private set; }
  11.  
  12. private readonly List<List<FreezeSprite>> _list = new List<List<FreezeSprite>>();
  13. private readonly InfiniteGrid<List<FreezeSprite>> _grid = new InfiniteGrid<List<FreezeSprite>>();
  14. private readonly RoomInfo _roomInfo;
  15. //网格划分的格子大小
  16. private readonly Vector2I _step;
  17. //当前残骸数量
  18. private int _count = 0;
  19. //最大残骸数量
  20. private int _maxCount = 1000;
  21. //每个格子中最大残骸数量
  22. private int _stepMaxCount = 30;
  23. private int _num = 0;
  24.  
  25. public RoomStaticSprite(RoomInfo roomInfo)
  26. {
  27. _roomInfo = roomInfo;
  28. _step = new Vector2I(30, 30);
  29. }
  30. public void Destroy()
  31. {
  32. if (IsDestroyed)
  33. {
  34. return;
  35. }
  36.  
  37. IsDestroyed = true;
  38.  
  39. _grid.ForEach((x, y, data) =>
  40. {
  41. foreach (var spriteData in data)
  42. {
  43. spriteData.Destroy();
  44. }
  45. data.Clear();
  46. });
  47. _grid.Clear();
  48. QueueFree();
  49. }
  50.  
  51. /// <summary>
  52. /// 添加静态精灵
  53. /// </summary>
  54. public void AddFreezeSprite(FreezeSprite freezeSprite)
  55. {
  56. var pos = ToGridPosition(freezeSprite.Position);
  57. var list = _grid.Get(pos);
  58. if (list == null)
  59. {
  60. list = new List<FreezeSprite>();
  61. _grid.Set(pos, list);
  62. _list.Add(list);
  63. }
  64. list.Add(freezeSprite);
  65. _count++;
  66. if (list.Count > _stepMaxCount) //检测单个step中残骸是否超出最大数量
  67. {
  68. var sprite = list[0];
  69. list.RemoveAt(0);
  70. sprite.Destroy();
  71. _count--;
  72. }
  73. else if (_count > _maxCount) //检测所有残骸是否超出最大数量
  74. {
  75. if (_num <= 0 || _list[0].Count == 0)
  76. {
  77. _num = 5;
  78. _list.Sort((l1, l2) => l2.Count - l1.Count);
  79. }
  80. else
  81. {
  82. _num--;
  83. }
  84.  
  85. var tempList = _list[0];
  86. if (tempList.Count > 0)
  87. {
  88. var sprite = tempList[0];
  89. tempList.RemoveAt(0);
  90. sprite.Destroy();
  91. _count--;
  92. }
  93. }
  94. }
  95.  
  96. /// <summary>
  97. /// 移除静态精灵
  98. /// </summary>
  99. public void RemoveFreezeSprite(FreezeSprite freezeSprite)
  100. {
  101. var pos = ToGridPosition(freezeSprite.Position);
  102. var list = _grid.Get(pos);
  103. if (list != null)
  104. {
  105. if (list.Remove(freezeSprite))
  106. {
  107. _count--;
  108. }
  109. }
  110. }
  111.  
  112. /// <summary>
  113. /// 获取指定圆形范围内所有已经被冻结的物体
  114. /// </summary>
  115. /// <param name="position">圆形中心点坐标</param>
  116. /// <param name="radius">圆形半径</param>
  117. /// <param name="unfreeze">是否解冻物体</param>
  118. public List<FreezeSprite> CollisionCircle(Vector2 position, float radius, bool unfreeze = false)
  119. {
  120. var len = radius * radius;
  121. var result = new List<FreezeSprite>();
  122. var startPosition = ToGridPosition(new Vector2(position.X - radius, position.Y - radius));
  123. var endPosition = ToGridPosition(new Vector2(position.X + radius, position.Y + radius));
  124. for (var x = startPosition.X; x <= endPosition.X; x++)
  125. {
  126. for (var y = startPosition.Y; y <= endPosition.Y; y++)
  127. {
  128. var data = _grid.Get(x, y);
  129. if (data != null)
  130. {
  131. for (var i = 0; i < data.Count; i++)
  132. {
  133. var freezeSprite = data[i];
  134. if (position.DistanceSquaredTo(freezeSprite.Position) < len)
  135. {
  136. result.Add(freezeSprite);
  137. if (unfreeze)
  138. {
  139. freezeSprite.HandlerUnfreezeSprite();
  140. data.RemoveAt(i--);
  141. _count--;
  142. }
  143. }
  144. }
  145. }
  146. }
  147. }
  148.  
  149. return result;
  150. }
  151.  
  152. private Vector2I ToGridPosition(Vector2 position)
  153. {
  154. var x = Mathf.FloorToInt(position.X / _step.X);
  155. var y = Mathf.FloorToInt(position.Y / _step.Y);
  156. return new Vector2I(x * _step.X, y * _step.Y);
  157. }
  158. }