Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / Grid.cs
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 网格数据结构, 通过 x 和 y 存储数据
  8. /// </summary>
  9. public class Grid<T>
  10. {
  11. /// <summary>
  12. /// 遍历网格数据回调
  13. /// </summary>
  14. public delegate void EachGridCallback(int x, int y, T data);
  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.  
  30. /// <summary>
  31. /// 设置指定xy位置的数据
  32. /// </summary>
  33. public void Set(int x, int y, T data)
  34. {
  35. if (_map.TryGetValue(x, out var value))
  36. {
  37. value[y] = data;
  38. }
  39. else
  40. {
  41. value = new Dictionary<int, T>();
  42. value.Add(y, data);
  43. _map.Add(x, value);
  44. }
  45. }
  46.  
  47. /// <summary>
  48. /// 获取指定xy位置的数据
  49. /// </summary>
  50. public T Get(int x, int y)
  51. {
  52. if (_map.TryGetValue(x, out var value))
  53. {
  54. return value[y];
  55. }
  56.  
  57. return default;
  58. }
  59. /// <summary>
  60. /// 往一个区域中填充指定的数据
  61. /// </summary>
  62. /// <param name="pos">起点位置</param>
  63. /// <param name="size">区域大小</param>
  64. /// <param name="data">数据</param>
  65. public void AddRect(Vector2 pos, Vector2 size, T data)
  66. {
  67. var x = (int)pos.X;
  68. var y = (int)pos.Y;
  69. for (var i = 0; i < size.X; i++)
  70. {
  71. for (var j = 0; j < size.Y; j++)
  72. {
  73. if (_map.TryGetValue(x + i, out var value))
  74. {
  75. value[y + j] = data;
  76. }
  77. else
  78. {
  79. value = new Dictionary<int, T>();
  80. value.Add(y + j, data);
  81. _map.Add(x + i, value);
  82. }
  83. }
  84. }
  85. }
  86.  
  87. /// <summary>
  88. /// 移除指定区域数据
  89. /// </summary>
  90. /// <param name="pos">起点位置</param>
  91. /// <param name="size">区域大小</param>
  92. public void RemoveRect(Vector2 pos, Vector2 size)
  93. {
  94. var x = (int)pos.X;
  95. var y = (int)pos.Y;
  96. for (var i = 0; i < size.X; i++)
  97. {
  98. for (var j = 0; j < size.Y; j++)
  99. {
  100. if (_map.TryGetValue(x + i, out var value))
  101. {
  102. value.Remove(y + j);
  103. if (value.Count == 0)
  104. {
  105. _map.Remove(x + i);
  106. }
  107. }
  108. }
  109. }
  110. }
  111.  
  112. /// <summary>
  113. /// 清除所有数据
  114. /// </summary>
  115. public void Clear()
  116. {
  117. _map.Clear();
  118. }
  119. /// <summary>
  120. /// 检测矩形区域内是否与其他数据有碰撞
  121. /// </summary>
  122. /// <param name="pos">起点位置</param>
  123. /// <param name="size">区域大小</param>
  124. public bool RectCollision(Vector2 pos, Vector2 size)
  125. {
  126. var x = (int)pos.X;
  127. var y = (int)pos.Y;
  128. var w = (int)size.X;
  129. var h = (int)size.Y;
  130. //先判断四个角
  131. if (Contains(x, y) || Contains(x + w - 1, y) || Contains(x, y + h - 1) || Contains(x + w - 1, y + h - 1))
  132. {
  133. return true;
  134. }
  135.  
  136. //逐个点判断
  137. for (int i = 1; i < w; i++)
  138. {
  139. for (int j = 0; j < h; j++)
  140. {
  141. if (Contains(x + i, y + j))
  142. {
  143. return true;
  144. }
  145. }
  146. }
  147.  
  148. return false;
  149. }
  150.  
  151. /// <summary>
  152. /// 遍历网格数据
  153. /// </summary>
  154. public void ForEach(EachGridCallback cb)
  155. {
  156. foreach (var pair1 in _map)
  157. {
  158. foreach (var pair2 in pair1.Value)
  159. {
  160. cb(pair1.Key, pair2.Key, pair2.Value);
  161. }
  162. }
  163. }
  164. }