Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / map / AffiliationArea.cs
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 房间归属区域
  8. /// </summary>
  9. public partial class AffiliationArea : Area2D, IDestroy
  10. {
  11. public bool IsDestroyed { get; private set; }
  12.  
  13. /// <summary>
  14. /// 当前实例所属房间
  15. /// </summary>
  16. public RoomInfo RoomInfo;
  17. /// <summary>
  18. /// 当前归属区域包含的所有物体对象, 物体进入另一个区域时才会从该集合中移除
  19. /// </summary>
  20. private readonly HashSet<ActivityObject> _includeItems = new HashSet<ActivityObject>();
  21.  
  22. /// <summary>
  23. /// 已经进入 AffiliationArea 所在范围内的物体, 物体一旦离开该区域就会立刻从该集合中删除
  24. /// </summary>
  25. private readonly HashSet<ActivityObject> _enterItems = new HashSet<ActivityObject>();
  26. /// <summary>
  27. /// 玩家是否是第一次进入
  28. /// </summary>
  29. public bool IsFirstEnterFlag { get; private set; } = true;
  30.  
  31. private bool _init = false;
  32. private Vector2 _initSize;
  33. private RectangleShape2D _shape;
  34. /// <summary>
  35. /// 根据矩形区域初始化归属区域
  36. /// </summary>
  37. public void Init(RoomInfo roomInfo, Rect2I rect2)
  38. {
  39. if (_init)
  40. {
  41. return;
  42. }
  43.  
  44. _init = true;
  45.  
  46. _initSize = rect2.Size;
  47. RoomInfo = roomInfo;
  48.  
  49. var collisionShape = new CollisionShape2D();
  50. collisionShape.GlobalPosition = rect2.Position + rect2.Size / 2;
  51. var shape = new RectangleShape2D();
  52. _shape = shape;
  53. shape.Size = rect2.Size;
  54. collisionShape.Shape = shape;
  55. AddChild(collisionShape);
  56. _Init();
  57. }
  58.  
  59. private void _Init()
  60. {
  61. Monitoring = true;
  62. Monitorable = false;
  63. CollisionLayer = PhysicsLayer.None;
  64. CollisionMask = PhysicsLayer.Prop | PhysicsLayer.Player | PhysicsLayer.Enemy | PhysicsLayer.Debris | PhysicsLayer.Throwing;
  65.  
  66. BodyEntered += OnBodyEntered;
  67. BodyExited += OnBodyExited;
  68. }
  69.  
  70. /// <summary>
  71. /// 将物体添加到当前所属区域中
  72. /// </summary>
  73. public void InsertItem(ActivityObject activityObject)
  74. {
  75. if (activityObject.AffiliationArea == this)
  76. {
  77. return;
  78. }
  79.  
  80. if (activityObject.AffiliationArea != null)
  81. {
  82. activityObject.AffiliationArea._includeItems.Remove(activityObject);
  83. }
  84. activityObject.AffiliationArea = this;
  85. _includeItems.Add(activityObject);
  86.  
  87. //如果是玩家
  88. if (activityObject == Player.Current)
  89. {
  90. OnPlayerInsertRoom();
  91. }
  92. }
  93.  
  94. /// <summary>
  95. /// 将物体从当前所属区域移除
  96. /// </summary>
  97. public void RemoveItem(ActivityObject activityObject)
  98. {
  99. if (activityObject.AffiliationArea == null)
  100. {
  101. return;
  102. }
  103. activityObject.AffiliationArea = null;
  104. _includeItems.Remove(activityObject);
  105. }
  106.  
  107. /// <summary>
  108. /// 获取该区域中物体的总数
  109. /// </summary>
  110. public int GetIncludeItemsCount()
  111. {
  112. return _includeItems.Count;
  113. }
  114.  
  115. /// <summary>
  116. /// 统计符合条件的数量
  117. /// </summary>
  118. /// <param name="handler">操作函数, 返回是否满足要求</param>
  119. public int FindIncludeItemsCount(Func<ActivityObject, bool> handler)
  120. {
  121. var count = 0;
  122. foreach (var activityObject in _includeItems)
  123. {
  124. if (!activityObject.IsDestroyed && handler(activityObject))
  125. {
  126. count++;
  127. }
  128. }
  129. return count;
  130. }
  131.  
  132. /// <summary>
  133. /// 查询所有符合条件的对象并返回
  134. /// </summary>
  135. /// <param name="handler">操作函数, 返回是否满足要求</param>
  136. public ActivityObject[] FindIncludeItems(Func<ActivityObject, bool> handler)
  137. {
  138. var list = new List<ActivityObject>();
  139. foreach (var activityObject in _includeItems)
  140. {
  141. if (!activityObject.IsDestroyed && handler(activityObject))
  142. {
  143. list.Add(activityObject);
  144. }
  145. }
  146. return list.ToArray();
  147. }
  148.  
  149. /// <summary>
  150. /// 检查是否有符合条件的对象
  151. /// </summary>
  152. /// <param name="handler">操作函数, 返回是否满足要求</param>
  153. public bool ExistIncludeItem(Func<ActivityObject, bool> handler)
  154. {
  155. foreach (var activityObject in _includeItems)
  156. {
  157. if (!activityObject.IsDestroyed && handler(activityObject))
  158. {
  159. return true;
  160. }
  161. }
  162.  
  163. return false;
  164. }
  165. /// <summary>
  166. /// 获取进入该区域中物体的总数
  167. /// </summary>
  168. public int GetEnterItemsCount()
  169. {
  170. return _enterItems.Count;
  171. }
  172. /// <summary>
  173. /// 统计进入该区域且符合条件的数量
  174. /// </summary>
  175. /// <param name="handler">操作函数, 返回是否满足要求</param>
  176. public int FindEnterItemsCount(Func<ActivityObject, bool> handler)
  177. {
  178. var count = 0;
  179. foreach (var activityObject in _enterItems)
  180. {
  181. if (!activityObject.IsDestroyed && handler(activityObject))
  182. {
  183. count++;
  184. }
  185. }
  186. return count;
  187. }
  188. /// <summary>
  189. /// 查询所有进入该区域且符合条件的对象并返回
  190. /// </summary>
  191. /// <param name="handler">操作函数, 返回是否满足要求</param>
  192. public ActivityObject[] FindEnterItems(Func<ActivityObject, bool> handler)
  193. {
  194. var list = new List<ActivityObject>();
  195. foreach (var activityObject in _enterItems)
  196. {
  197. if (!activityObject.IsDestroyed && handler(activityObject))
  198. {
  199. list.Add(activityObject);
  200. }
  201. }
  202. return list.ToArray();
  203. }
  204.  
  205. /// <summary>
  206. /// 检查是否有进入该区域且符合条件的对象
  207. /// </summary>
  208. /// <param name="handler">操作函数, 返回是否满足要求</param>
  209. public bool ExistEnterItem(Func<ActivityObject, bool> handler)
  210. {
  211. foreach (var activityObject in _enterItems)
  212. {
  213. if (!activityObject.IsDestroyed && handler(activityObject))
  214. {
  215. return true;
  216. }
  217. }
  218.  
  219. return false;
  220. }
  221.  
  222. /// <summary>
  223. /// 返回物体是否进入了该区域
  224. /// </summary>
  225. public bool IsEnter(ActivityObject activityObject)
  226. {
  227. return _enterItems.Contains(activityObject);
  228. }
  229. private void OnBodyEntered(Node2D body)
  230. {
  231. if (body is ActivityObject activityObject)
  232. {
  233. _enterItems.Add(activityObject);
  234. //注意需要延时调用
  235. CallDeferred(nameof(InsertItem), activityObject);
  236. }
  237. }
  238. private void OnBodyExited(Node2D body)
  239. {
  240. if (body is ActivityObject activityObject)
  241. {
  242. _enterItems.Remove(activityObject);
  243. }
  244. }
  245.  
  246. //玩家进入房间
  247. private void OnPlayerInsertRoom()
  248. {
  249. if (IsFirstEnterFlag)
  250. {
  251. EventManager.EmitEvent(EventEnum.OnPlayerFirstEnterRoom, RoomInfo);
  252. }
  253. EventManager.EmitEvent(EventEnum.OnPlayerEnterRoom, RoomInfo);
  254. IsFirstEnterFlag = false;
  255. }
  256.  
  257. public void Destroy()
  258. {
  259. if (IsDestroyed)
  260. {
  261. return;
  262. }
  263.  
  264. IsDestroyed = true;
  265. QueueFree();
  266. _includeItems.Clear();
  267. _enterItems.Clear();
  268. }
  269.  
  270. /// <summary>
  271. /// 在初始区域的基础上扩展区域, size为扩展大小
  272. /// </summary>
  273. public void ExtendedRegion(Vector2 size)
  274. {
  275. _shape.Size = _initSize + size;
  276. }
  277.  
  278. /// <summary>
  279. /// 将区域还原到初始大小
  280. /// </summary>
  281. public void RestoreRegion()
  282. {
  283. _shape.Size = _initSize;
  284. }
  285. }