Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / image / RoomStaticSprite.cs
@小李xl 小李xl on 4 Nov 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 Grid<List<FreezeSprite>> _grid = new Grid<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. public List<FreezeSprite> CollisionCircle(Vector2 position, float radius, bool unfreeze = false)
  113. {
  114. var len = radius * radius;
  115. var result = new List<FreezeSprite>();
  116. var startPosition = ToGridPosition(new Vector2(position.X - radius, position.Y - radius));
  117. var endPosition = ToGridPosition(new Vector2(position.X + radius, position.Y + radius));
  118. for (var x = startPosition.X; x <= endPosition.X; x++)
  119. {
  120. for (var y = startPosition.Y; y <= endPosition.Y; y++)
  121. {
  122. var data = _grid.Get(x, y);
  123. if (data != null)
  124. {
  125. for (var i = 0; i < data.Count; i++)
  126. {
  127. var freezeSprite = data[i];
  128. if (position.DistanceSquaredTo(freezeSprite.Position) < len)
  129. {
  130. result.Add(freezeSprite);
  131. if (unfreeze)
  132. {
  133. freezeSprite.HandlerUnfreezeSprite();
  134. data.RemoveAt(i--);
  135. _count--;
  136. }
  137. }
  138. }
  139. }
  140. }
  141. }
  142.  
  143. return result;
  144. }
  145.  
  146. private Vector2I ToGridPosition(Vector2 position)
  147. {
  148. var x = Mathf.FloorToInt(position.X / _step.X);
  149. var y = Mathf.FloorToInt(position.Y / _step.Y);
  150. return new Vector2I(x * _step.X, y * _step.Y);
  151. }
  152. }