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