Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / InfiniteGrid.cs
@小李xl 小李xl on 24 Nov 2023 4 KB 制作消除效果中
  1.  
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 无限大的网格数据结构, 通过 x 和 y 存储数据
  7. /// </summary>
  8. public class InfiniteGrid<T>
  9. {
  10. /// <summary>
  11. /// 遍历网格数据回调
  12. /// </summary>
  13. public delegate void EachGridCallback(int x, int y, T data);
  14.  
  15. private readonly Dictionary<int, Dictionary<int, T>> _map = new Dictionary<int, Dictionary<int, T>>();
  16.  
  17. /// <summary>
  18. /// 返回指定xy位置是否存在数据
  19. /// </summary>
  20. public bool Contains(int x, int y)
  21. {
  22. if (_map.TryGetValue(x, out var value))
  23. {
  24. return value.ContainsKey(y);
  25. }
  26.  
  27. return false;
  28. }
  29. /// <summary>
  30. /// 返回指定xy位置是否有数据
  31. /// </summary>
  32. public bool Contains(Vector2I pos)
  33. {
  34. return Contains(pos.X, pos.Y);
  35. }
  36.  
  37. /// <summary>
  38. /// 设置指定xy位置的数据
  39. /// </summary>
  40. public void Set(int x, int y, T data)
  41. {
  42. if (_map.TryGetValue(x, out var value))
  43. {
  44. value[y] = data;
  45. }
  46. else
  47. {
  48. value = new Dictionary<int, T>();
  49. value.Add(y, data);
  50. _map.Add(x, value);
  51. }
  52. }
  53.  
  54. /// <summary>
  55. /// 设置指定坐标的数据
  56. /// </summary>
  57. public void Set(Vector2I pos, T data)
  58. {
  59. Set(pos.X, pos.Y, data);
  60. }
  61.  
  62. /// <summary>
  63. /// 获取指定xy位置的数据
  64. /// </summary>
  65. public T Get(int x, int y)
  66. {
  67. if (_map.TryGetValue(x, out var value))
  68. {
  69. if (value.TryGetValue(y, out var v))
  70. {
  71. return v;
  72. }
  73. }
  74.  
  75. return default;
  76. }
  77.  
  78. /// <summary>
  79. /// 获取指定坐标的数据
  80. /// </summary>
  81. public T Get(Vector2I pos)
  82. {
  83. return Get(pos.X, pos.Y);
  84. }
  85.  
  86. /// <summary>
  87. /// 移除指定xy位置存储的数据
  88. /// </summary>
  89. public bool Remove(int x, int y)
  90. {
  91. if (_map.TryGetValue(x, out var value))
  92. {
  93. return value.Remove(y);
  94. }
  95.  
  96. return false;
  97. }
  98. /// <summary>
  99. /// 往一个区域中填充指定的数据
  100. /// </summary>
  101. /// <param name="pos">起点位置</param>
  102. /// <param name="size">区域大小</param>
  103. /// <param name="data">数据</param>
  104. public void SetRect(Vector2I pos, Vector2I size, T data)
  105. {
  106. var x = pos.X;
  107. var y = pos.Y;
  108. for (var i = 0; i < size.X; i++)
  109. {
  110. for (var j = 0; j < size.Y; j++)
  111. {
  112. if (_map.TryGetValue(x + i, out var value))
  113. {
  114. value[y + j] = data;
  115. }
  116. else
  117. {
  118. value = new Dictionary<int, T>();
  119. value.Add(y + j, data);
  120. _map.Add(x + i, value);
  121. }
  122. }
  123. }
  124. }
  125.  
  126. /// <summary>
  127. /// 移除指定区域数据
  128. /// </summary>
  129. /// <param name="pos">起点位置</param>
  130. /// <param name="size">区域大小</param>
  131. public void RemoveRect(Vector2I pos, Vector2I size)
  132. {
  133. var x = pos.X;
  134. var y = pos.Y;
  135. for (var i = 0; i < size.X; i++)
  136. {
  137. for (var j = 0; j < size.Y; j++)
  138. {
  139. if (_map.TryGetValue(x + i, out var value))
  140. {
  141. value.Remove(y + j);
  142. if (value.Count == 0)
  143. {
  144. _map.Remove(x + i);
  145. }
  146. }
  147. }
  148. }
  149. }
  150.  
  151. /// <summary>
  152. /// 清除所有数据
  153. /// </summary>
  154. public void Clear()
  155. {
  156. _map.Clear();
  157. }
  158. /// <summary>
  159. /// 检测矩形区域内是否与其他数据有碰撞
  160. /// </summary>
  161. /// <param name="pos">起点位置</param>
  162. /// <param name="size">区域大小</param>
  163. public bool RectCollision(Vector2I pos, Vector2I size)
  164. {
  165. var x = pos.X;
  166. var y = pos.Y;
  167. var w = size.X;
  168. var h = size.Y;
  169. //先判断四个角
  170. if (Contains(x, y) || Contains(x + w - 1, y) || Contains(x, y + h - 1) || Contains(x + w - 1, y + h - 1))
  171. {
  172. return true;
  173. }
  174.  
  175. //逐个点判断
  176. for (int i = 1; i < w; i++)
  177. {
  178. for (int j = 0; j < h; j++)
  179. {
  180. if (Contains(x + i, y + j))
  181. {
  182. return true;
  183. }
  184. }
  185. }
  186.  
  187. return false;
  188. }
  189.  
  190. /// <summary>
  191. /// 遍历网格数据
  192. /// </summary>
  193. public void ForEach(EachGridCallback cb)
  194. {
  195. foreach (var pair1 in _map)
  196. {
  197. foreach (var pair2 in pair1.Value)
  198. {
  199. cb(pair1.Key, pair2.Key, pair2.Value);
  200. }
  201. }
  202. }
  203. }