using System; using System.Collections.Generic; using Godot; /// <summary> /// 归属区域 /// </summary> public partial class AffiliationArea : Area2D { /// <summary> /// 当前实例所属房间 /// </summary> public RoomInfo RoomInfo; /// <summary> /// 当前归属区域包含的所有物体对象 /// </summary> private readonly HashSet<ActivityObject> _includeItems = new HashSet<ActivityObject>(); /// <summary> /// 玩家是否是第一次进入 /// </summary> public bool IsFirstEnterFlag { get; private set; } = true; private bool _init = false; /// <summary> /// 根据矩形区域初始化归属区域 /// </summary> public void Init(RoomInfo roomInfo, Rect2 rect2) { if (_init) { return; } _init = true; RoomInfo = roomInfo; var collisionShape = new CollisionShape2D(); collisionShape.GlobalPosition = rect2.Position + rect2.Size / 2; var shape = new RectangleShape2D(); shape.Size = rect2.Size; collisionShape.Shape = shape; AddChild(collisionShape); _Init(); } private void _Init() { Monitoring = true; Monitorable = false; CollisionLayer = PhysicsLayer.None; CollisionMask = PhysicsLayer.Prop | PhysicsLayer.Player | PhysicsLayer.Enemy | PhysicsLayer.Shell | PhysicsLayer.Throwing; BodyEntered += OnBodyEntered; } /// <summary> /// 将物体添加到当前所属区域中 /// </summary> public void InsertItem(ActivityObject activityObject) { if (activityObject.AffiliationArea == this) { return; } if (activityObject.AffiliationArea != null) { _includeItems.Remove(activityObject); } activityObject.AffiliationArea = this; _includeItems.Add(activityObject); //如果是玩家 if (activityObject == Player.Current) { OnPlayerEnterRoom(); } } /// <summary> /// 将物体从当前所属区域移除 /// </summary> public void RemoveItem(ActivityObject activityObject) { if (activityObject.AffiliationArea == null) { return; } activityObject.AffiliationArea = null; _includeItems.Remove(activityObject); } /// <summary> /// 获取该区域中物体的总数 /// </summary> public int GetIncludeItemsCount() { return _includeItems.Count; } /// <summary> /// 统计符合条件的数量 /// </summary> /// <param name="handler">操作函数, 返回是否满足要求</param> public int FindIncludeItemsCount(Func<ActivityObject, bool> handler) { var count = 0; foreach (var activityObject in _includeItems) { if (handler(activityObject)) { count++; } } return count; } /// <summary> /// 查询所有符合条件的对象并返回 /// </summary> /// <param name="handler">操作函数, 返回是否满足要求</param> public ActivityObject[] FindIncludeItems(Func<ActivityObject, bool> handler) { var list = new List<ActivityObject>(); foreach (var activityObject in _includeItems) { if (handler(activityObject)) { list.Add(activityObject); } } return list.ToArray(); } /// <summary> /// 检查是否有符合条件的对象 /// </summary> /// <param name="handler">操作函数, 返回是否满足要求</param> public bool ExistIncludeItem(Func<ActivityObject, bool> handler) { foreach (var activityObject in _includeItems) { if (handler(activityObject)) { return true; } } return false; } private void OnBodyEntered(Node2D body) { if (body is ActivityObject activityObject) { //注意需要延时调用 CallDeferred(nameof(InsertItem), activityObject); } } //玩家进入房间 private void OnPlayerEnterRoom() { if (IsFirstEnterFlag) { EventManager.EmitEvent(EventEnum.OnPlayerFirstEnterRoom, RoomInfo); IsFirstEnterFlag = false; } EventManager.EmitEvent(EventEnum.OnPlayerEnterRoom, RoomInfo); } }