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. if (_includeItems.Add(activityObject))
  86. {
  87. //如果是玩家
  88. if (activityObject == Player.Current)
  89. {
  90. CallDeferred(nameof(OnPlayerInsertRoom));
  91. }
  92. }
  93. }
  94.  
  95. /// <summary>
  96. /// 将物体从当前所属区域移除
  97. /// </summary>
  98. public void RemoveItem(ActivityObject activityObject)
  99. {
  100. if (activityObject.AffiliationArea == null)
  101. {
  102. return;
  103. }
  104. activityObject.AffiliationArea = null;
  105. _includeItems.Remove(activityObject);
  106. }
  107.  
  108. /// <summary>
  109. /// 获取该区域中物体的总数
  110. /// </summary>
  111. public int GetIncludeItemsCount()
  112. {
  113. return _includeItems.Count;
  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. /// <summary>
  222. /// 遍历该该区域的物体
  223. /// </summary>
  224. /// <param name="handler">操作函数, 返回 false 表示跳出循环</param>
  225. public void ForEachIncludeItems(Func<ActivityObject, bool> handler)
  226. {
  227. foreach (var activityObject in _includeItems)
  228. {
  229. if (!activityObject.IsDestroyed && handler(activityObject))
  230. {
  231. return;
  232. }
  233. }
  234. }
  235.  
  236. /// <summary>
  237. /// 遍历该进入该区域的物体
  238. /// </summary>
  239. /// <param name="handler">操作函数, 返回 false 表示跳出循环</param>
  240. public void ForEachEnterItems(Func<ActivityObject, bool> handler)
  241. {
  242. foreach (var activityObject in _enterItems)
  243. {
  244. if (!activityObject.IsDestroyed && handler(activityObject))
  245. {
  246. return;
  247. }
  248. }
  249. }
  250.  
  251.  
  252. /// <summary>
  253. /// 返回物体是否进入了该区域
  254. /// </summary>
  255. public bool IsEnter(ActivityObject activityObject)
  256. {
  257. return _enterItems.Contains(activityObject);
  258. }
  259. private void OnBodyEntered(Node2D body)
  260. {
  261. if (body is ActivityObject activityObject)
  262. {
  263. _enterItems.Add(activityObject);
  264. InsertItem(activityObject);
  265. }
  266. }
  267. private void OnBodyExited(Node2D body)
  268. {
  269. if (body is ActivityObject activityObject)
  270. {
  271. _enterItems.Remove(activityObject);
  272. }
  273. }
  274.  
  275. //玩家进入房间
  276. private void OnPlayerInsertRoom()
  277. {
  278. if (IsFirstEnterFlag)
  279. {
  280. EventManager.EmitEvent(EventEnum.OnPlayerFirstEnterRoom, RoomInfo);
  281. }
  282. EventManager.EmitEvent(EventEnum.OnPlayerEnterRoom, RoomInfo);
  283. IsFirstEnterFlag = false;
  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. }