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. CallDeferred(nameof(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. /// <summary>
  115. /// 统计符合条件的数量
  116. /// </summary>
  117. /// <param name="handler">操作函数, 返回是否满足要求</param>
  118. public int FindIncludeItemsCount(Func<ActivityObject, bool> handler)
  119. {
  120. var count = 0;
  121. foreach (var activityObject in _includeItems)
  122. {
  123. if (!activityObject.IsDestroyed && handler(activityObject))
  124. {
  125. count++;
  126. }
  127. }
  128. return count;
  129. }
  130.  
  131. /// <summary>
  132. /// 查询所有符合条件的对象并返回
  133. /// </summary>
  134. /// <param name="handler">操作函数, 返回是否满足要求</param>
  135. public ActivityObject[] FindIncludeItems(Func<ActivityObject, bool> handler)
  136. {
  137. var list = new List<ActivityObject>();
  138. foreach (var activityObject in _includeItems)
  139. {
  140. if (!activityObject.IsDestroyed && handler(activityObject))
  141. {
  142. list.Add(activityObject);
  143. }
  144. }
  145. return list.ToArray();
  146. }
  147.  
  148. /// <summary>
  149. /// 检查是否有符合条件的对象
  150. /// </summary>
  151. /// <param name="handler">操作函数, 返回是否满足要求</param>
  152. public bool ExistIncludeItem(Func<ActivityObject, bool> handler)
  153. {
  154. foreach (var activityObject in _includeItems)
  155. {
  156. if (!activityObject.IsDestroyed && handler(activityObject))
  157. {
  158. return true;
  159. }
  160. }
  161.  
  162. return false;
  163. }
  164. /// <summary>
  165. /// 获取进入该区域中物体的总数
  166. /// </summary>
  167. public int GetEnterItemsCount()
  168. {
  169. return _enterItems.Count;
  170. }
  171. /// <summary>
  172. /// 统计进入该区域且符合条件的数量
  173. /// </summary>
  174. /// <param name="handler">操作函数, 返回是否满足要求</param>
  175. public int FindEnterItemsCount(Func<ActivityObject, bool> handler)
  176. {
  177. var count = 0;
  178. foreach (var activityObject in _enterItems)
  179. {
  180. if (!activityObject.IsDestroyed && handler(activityObject))
  181. {
  182. count++;
  183. }
  184. }
  185. return count;
  186. }
  187. /// <summary>
  188. /// 查询所有进入该区域且符合条件的对象并返回
  189. /// </summary>
  190. /// <param name="handler">操作函数, 返回是否满足要求</param>
  191. public ActivityObject[] FindEnterItems(Func<ActivityObject, bool> handler)
  192. {
  193. var list = new List<ActivityObject>();
  194. foreach (var activityObject in _enterItems)
  195. {
  196. if (!activityObject.IsDestroyed && handler(activityObject))
  197. {
  198. list.Add(activityObject);
  199. }
  200. }
  201. return list.ToArray();
  202. }
  203.  
  204. /// <summary>
  205. /// 检查是否有进入该区域且符合条件的对象
  206. /// </summary>
  207. /// <param name="handler">操作函数, 返回是否满足要求</param>
  208. public bool ExistEnterItem(Func<ActivityObject, bool> handler)
  209. {
  210. foreach (var activityObject in _enterItems)
  211. {
  212. if (!activityObject.IsDestroyed && handler(activityObject))
  213. {
  214. return true;
  215. }
  216. }
  217.  
  218. return false;
  219. }
  220. /// <summary>
  221. /// 遍历该该区域的物体
  222. /// </summary>
  223. /// <param name="handler">操作函数, 返回 false 表示跳出循环</param>
  224. public void ForEachIncludeItems(Func<ActivityObject, bool> handler)
  225. {
  226. foreach (var activityObject in _includeItems)
  227. {
  228. if (!activityObject.IsDestroyed && handler(activityObject))
  229. {
  230. return;
  231. }
  232. }
  233. }
  234.  
  235. /// <summary>
  236. /// 遍历该进入该区域的物体
  237. /// </summary>
  238. /// <param name="handler">操作函数, 返回 false 表示跳出循环</param>
  239. public void ForEachEnterItems(Func<ActivityObject, bool> handler)
  240. {
  241. foreach (var activityObject in _enterItems)
  242. {
  243. if (!activityObject.IsDestroyed && handler(activityObject))
  244. {
  245. return;
  246. }
  247. }
  248. }
  249.  
  250.  
  251. /// <summary>
  252. /// 返回物体是否进入了该区域
  253. /// </summary>
  254. public bool IsEnter(ActivityObject activityObject)
  255. {
  256. return _enterItems.Contains(activityObject);
  257. }
  258. private void OnBodyEntered(Node2D body)
  259. {
  260. if (body is ActivityObject activityObject)
  261. {
  262. _enterItems.Add(activityObject);
  263. InsertItem(activityObject);
  264. }
  265. }
  266. private void OnBodyExited(Node2D body)
  267. {
  268. if (body is ActivityObject activityObject)
  269. {
  270. _enterItems.Remove(activityObject);
  271. }
  272. }
  273.  
  274. //玩家进入房间
  275. private void OnPlayerInsertRoom()
  276. {
  277. if (IsFirstEnterFlag)
  278. {
  279. EventManager.EmitEvent(EventEnum.OnPlayerFirstEnterRoom, RoomInfo);
  280. }
  281. EventManager.EmitEvent(EventEnum.OnPlayerEnterRoom, RoomInfo);
  282. IsFirstEnterFlag = false;
  283. }
  284.  
  285. public void Destroy()
  286. {
  287. if (IsDestroyed)
  288. {
  289. return;
  290. }
  291.  
  292. IsDestroyed = true;
  293. QueueFree();
  294. _includeItems.Clear();
  295. _enterItems.Clear();
  296. }
  297.  
  298. /// <summary>
  299. /// 在初始区域的基础上扩展区域, size为扩展大小
  300. /// </summary>
  301. public void ExtendedRegion(Vector2 size)
  302. {
  303. _shape.Size = _initSize + size;
  304. }
  305.  
  306. /// <summary>
  307. /// 将区域还原到初始大小
  308. /// </summary>
  309. public void RestoreRegion()
  310. {
  311. _shape.Size = _initSize;
  312. }
  313. }