Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / image / RoomStaticSprite.cs
  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. return true;
  47. });
  48. _grid.Clear();
  49. QueueFree();
  50. }
  51.  
  52. /// <summary>
  53. /// 添加静态精灵
  54. /// </summary>
  55. public void AddFreezeSprite(FreezeSprite freezeSprite)
  56. {
  57. var pos = ToGridPosition(freezeSprite.Position);
  58. var list = _grid.Get(pos);
  59. if (list == null)
  60. {
  61. list = new List<FreezeSprite>();
  62. _grid.Set(pos, list);
  63. _list.Add(list);
  64. }
  65. list.Add(freezeSprite);
  66. _count++;
  67. if (list.Count > _stepMaxCount) //检测单个step中残骸是否超出最大数量
  68. {
  69. var sprite = list[0];
  70. list.RemoveAt(0);
  71. sprite.Destroy();
  72. _count--;
  73. }
  74. else if (_count > _maxCount) //检测所有残骸是否超出最大数量
  75. {
  76. if (_num <= 0 || _list[0].Count == 0)
  77. {
  78. _num = 5;
  79. _list.Sort((l1, l2) => l2.Count - l1.Count);
  80. }
  81. else
  82. {
  83. _num--;
  84. }
  85.  
  86. var tempList = _list[0];
  87. if (tempList.Count > 0)
  88. {
  89. var sprite = tempList[0];
  90. tempList.RemoveAt(0);
  91. sprite.Destroy();
  92. _count--;
  93. }
  94. }
  95. }
  96.  
  97. /// <summary>
  98. /// 移除静态精灵
  99. /// </summary>
  100. public void RemoveFreezeSprite(FreezeSprite freezeSprite)
  101. {
  102. var pos = ToGridPosition(freezeSprite.Position);
  103. var list = _grid.Get(pos);
  104. if (list != null)
  105. {
  106. if (list.Remove(freezeSprite))
  107. {
  108. _count--;
  109. }
  110. }
  111. }
  112.  
  113. /// <summary>
  114. /// 获取指定圆形范围内所有已经被冻结的物体
  115. /// </summary>
  116. /// <param name="position">圆形中心点坐标</param>
  117. /// <param name="radius">圆形半径</param>
  118. /// <param name="unfreeze">是否解冻物体</param>
  119. public List<FreezeSprite> CollisionCircle(Vector2 position, float radius, bool unfreeze = false)
  120. {
  121. var len = radius * radius;
  122. var result = new List<FreezeSprite>();
  123. var startPosition = ToGridPosition(new Vector2(position.X - radius, position.Y - radius));
  124. var endPosition = ToGridPosition(new Vector2(position.X + radius, position.Y + radius));
  125. for (var x = startPosition.X; x <= endPosition.X; x++)
  126. {
  127. for (var y = startPosition.Y; y <= endPosition.Y; y++)
  128. {
  129. var data = _grid.Get(x, y);
  130. if (data != null)
  131. {
  132. for (var i = 0; i < data.Count; i++)
  133. {
  134. var freezeSprite = data[i];
  135. if (position.DistanceSquaredTo(freezeSprite.Position) < len)
  136. {
  137. result.Add(freezeSprite);
  138. if (unfreeze)
  139. {
  140. freezeSprite.HandlerUnfreezeSprite();
  141. data.RemoveAt(i--);
  142. _count--;
  143. }
  144. }
  145. }
  146. }
  147. }
  148. }
  149.  
  150. return result;
  151. }
  152.  
  153. private Vector2I ToGridPosition(Vector2 position)
  154. {
  155. var x = Mathf.FloorToInt(position.X / _step.X);
  156. var y = Mathf.FloorToInt(position.Y / _step.Y);
  157. return new Vector2I(x * _step.X, y * _step.Y);
  158. }
  159. }