/// <summary> /// TryGetValue /// </summary> /// <param name="target">target MinValue = -3.402823E+38f</param> /// <param name="node"></param> /// <returns></returns> public bool TryGetValue(float target, out AoiNode node) { node = null; var cur = _header; while (cur != null) { while (cur.Right != null && cur.Right.Value < target) { cur = cur.Right; } if (cur.Right != null && Math.Abs(cur.Right.Value - target) < _limit) { node = cur.Right; while (node.Down != null) { node = node.Down; } return(true); } cur = cur.Down; } return(false); }
/// <summary> /// 更新节点 /// </summary> /// <param name="node">Aoi节点</param> /// <param name="area">区域距离</param> /// <param name="x">X轴位置</param> /// <param name="y">Y轴位置</param> /// <returns></returns> public AoiNode Update(AoiNode node, Vector2 area, float x, float y) { // 把新的AOI节点转移到旧的节点里 node.AoiInfo.MoveOnlySet = node.AoiInfo.MovesSet.Select(d => d).ToHashSet(); // 移动到新的位置 Move(node, x, y); // 查找周围坐标 Find(node, area); // 差集计算 node.AoiInfo.EntersSet = node.AoiInfo.MovesSet.Except(node.AoiInfo.MoveOnlySet).ToHashSet(); // 把自己添加到进入点的人 foreach (var enterNode in node.AoiInfo.EntersSet) { GetNode(enterNode).AoiInfo.MovesSet.Add(node.Id); } node.AoiInfo.LeavesSet = node.AoiInfo.MoveOnlySet.Except(node.AoiInfo.MovesSet).ToHashSet(); node.AoiInfo.MoveOnlySet = node.AoiInfo.MoveOnlySet.Except(node.AoiInfo.EntersSet) .Except(node.AoiInfo.LeavesSet).ToHashSet(); return(node); }
/// <summary> /// 更新节点 /// </summary> /// <param name="node">Aoi节点</param> /// <param name="area">区域距离</param> /// <param name="x">X轴位置</param> /// <param name="y">Y轴位置</param> /// <returns></returns> public AoiNode UpdateNode(AoiNode node, Vector2 area, float x, float y) { // 把新的AOI节点转移到旧的节点里 node.AoiInfo.MoveOnlySet = node.AoiInfo.MovesSet.Select(d => d).ToHashSet(); // 移动到新的位置 Move(node, x, y); // 查找周围坐标 FindAoi(node, area); // 差集计算 node.AoiInfo.EntersSet = node.AoiInfo.MovesSet.Except(node.AoiInfo.MoveOnlySet).ToHashSet(); node.AoiInfo.LeavesSet = node.AoiInfo.MoveOnlySet.Except(node.AoiInfo.MovesSet).ToHashSet(); node.AoiInfo.MoveOnlySet = node.AoiInfo.MoveOnlySet.Except(node.AoiInfo.EntersSet) .Except(node.AoiInfo.LeavesSet).ToHashSet(); return(node); }
/// <summary> /// Add node /// </summary> /// <param name="target">target MinValue = -3.402823E+38f</param> /// <param name="entity"></param> /// <returns></returns> public AoiNode Add(float target, AoiEntity entity = null) { var rLayer = 1; if (_header == null) { rLayer = _maxLayer; var tempHeader = _header = new AoiNode(rLayer, target, entity); for (var layer = _maxLayer - 1; layer >= 1; --layer) { _header = _header.Down = new AoiNode(layer, target, top: _header); } _header = tempHeader; return(null); } while (rLayer < _maxLayer && _random.Next(2) == 0) { ++rLayer; } AoiNode cur = _header, insertNode = null, lastLayerNode = null; for (var layer = _maxLayer; layer >= 1; --layer) { while (cur.Right != null && cur.Right.Value < target) { cur = cur.Right; } if (layer <= rLayer) { insertNode = new AoiNode(layer, target, entity: entity, left: cur, right: cur.Right); if (cur.Right != null) { cur.Right.Left = insertNode; } cur.Right = insertNode; if (lastLayerNode != null) { lastLayerNode.Down = insertNode; insertNode.Top = lastLayerNode; } lastLayerNode = insertNode; } cur = cur.Down; } Count++; return(insertNode); }
/// <summary> /// 根据指定范围查找周围的坐标 /// </summary> /// <param name="node">Aoi节点</param> /// <param name="area">区域距离</param> public AoiNode Find(AoiNode node, Vector2 area) { node.AoiInfo.MovesSet.Clear(); for (var i = 0; i < 2; i++) { var cur = i == 0 ? node.Link.XNode.Next : node.Link.XNode.Previous; while (cur != null) { if (Math.Abs(Math.Abs(cur.Value.Position.X) - Math.Abs(node.Position.X)) > area.X) { break; } else if (Math.Abs(Math.Abs(cur.Value.Position.Y) - Math.Abs(node.Position.Y)) <= area.Y) { if (Distance(node.Position, cur.Value.Position) <= area.X) { if (!node.AoiInfo.MovesSet.Contains(cur.Value.Id)) { node.AoiInfo.MovesSet.Add(cur.Value.Id); } } } cur = i == 0 ? cur.Next : cur.Previous; } } for (var i = 0; i < 2; i++) { var cur = i == 0 ? node.Link.YNode.Next : node.Link.YNode.Previous; while (cur != null) { if (Math.Abs(Math.Abs(cur.Value.Position.Y) - Math.Abs(node.Position.Y)) > area.Y) { break; } else if (Math.Abs(Math.Abs(cur.Value.Position.X) - Math.Abs(node.Position.X)) <= area.X) { if (Distance(node.Position, cur.Value.Position) <= area.Y) { if (!node.AoiInfo.MovesSet.Contains(cur.Value.Id)) { node.AoiInfo.MovesSet.Add(cur.Value.Id); } } } cur = i == 0 ? cur.Next :cur.Previous; } } return(node); }
/// <summary> /// Circuit Breaker /// </summary> /// <param name="cur"></param> private void CircuitBreaker(AoiNode cur) { if (cur.Left != null) { cur.Left.Right = cur.Right; } if (cur.Right != null) { cur.Right.Left = cur.Left; } cur.Left = null; cur.Right = null; }
/// <summary> /// Remove /// </summary> /// <param name="node"></param> public void Remove(AoiNode node) { var cur = node; while (cur != null) { var tmp = cur; CircuitBreaker(tmp); cur = cur.Top; } Count--; }
public AoiNode Add(float target, AoiEntity entity) { var rLevel = 1; while (rLevel <= _level && _random.Next(2) == 0) { ++rLevel; } if (rLevel > _level) { _level = rLevel; _header = AoiPool.Instance.Fetch <AoiNode>().Init(_level, target, entity, null, null, null, _header); } AoiNode cur = _header, last = null; for (var l = _level; l >= 1; --l) { while (cur.Right != null && cur.Right.Value < target) { cur = cur.Right; } if (l <= rLevel) { cur.Right = AoiPool.Instance.Fetch <AoiNode>().Init(l, target, entity, cur, cur.Right, null, null); if (last != null) { last.Down = cur.Right; cur.Right.Top = last; } last = cur.Right; if (l == 1) { cur = cur.Right; break; } } cur = cur.Down; } Count++; return(cur); }
public void Recycle() { if (_isRecycle) { return; } X = null; Y = null; Key = 0; ViewEntity.Clear(); ViewEntityBak.Clear(); _isRecycle = true; }
public void Recycle() { if (_isRecycle) { return; } X = null; Y = null; Key = 0; ViewEntity.Clear(); ViewEntityBak.Clear(); _isRecycle = true; AoiPool.Instance.Recycle(this); }
/// <summary> /// 新加入AOI /// </summary> /// <param name="id">一般是角色的ID等其他标识ID</param> /// <param name="x">X轴位置</param> /// <param name="y">Y轴位置</param> /// <returns></returns> public AoiNode Enter(long id, float x, float y) { if (_nodes.TryGetValue(id, out var node)) { return(node); } node = new AoiNode().Init(id, x, y); _xLinks.Insert(node); _yLinks.Insert(node); _nodes[node.Id] = node; return(node); }
public AoiNode Update(AoiNode node, Vector2 area) { return(Update(node, area, node.Position.X, node.Position.Y)); }
/// <summary> /// 移动 /// </summary> /// <param name="node">Aoi节点</param> /// <param name="x">X轴位置</param> /// <param name="y">Y轴位置</param> private void Move(AoiNode node, float x, float y) { #region 移动X轴 if (Math.Abs(node.Position.X - x) > 0) { if (x > node.Position.X) { var cur = node.Link.XNode.Next; while (cur != null) { if (x < cur.Value.Position.X) { _xLinks.Remove(node.Link.XNode); node.Position.X = x; node.Link.XNode = _xLinks.AddBefore(cur, node); break; } else if (cur.Next == null) { _xLinks.Remove(node.Link.XNode); node.Position.X = x; node.Link.XNode = _xLinks.AddAfter(cur, node); break; } cur = cur.Next; } } else { var cur = node.Link.XNode.Previous; while (cur != null) { if (x > cur.Value.Position.X) { _xLinks.Remove(node.Link.XNode); node.Position.X = x; node.Link.XNode = _xLinks.AddAfter(cur, node); break; } else if (cur.Previous == null) { _xLinks.Remove(node.Link.XNode); node.Position.X = x; node.Link.XNode = _xLinks.AddAfter(cur, node); break; } cur = cur.Previous; } } } #endregion #region 移动Y轴 if (Math.Abs(node.Position.Y - y) > 0) { if (y > node.Position.Y) { var cur = node.Link.YNode.Next; while (cur != null) { if (y < cur.Value.Position.Y) { _yLinks.Remove(node.Link.YNode); node.Position.Y = y; node.Link.YNode = _yLinks.AddBefore(cur, node); break; } else if (cur.Next == null) { _yLinks.Remove(node.Link.YNode); node.Position.Y = y; node.Link.YNode = _yLinks.AddAfter(cur, node); break; } cur = cur.Next; } } else { var cur = node.Link.YNode.Previous; while (cur != null) { if (y > cur.Value.Position.Y) { _yLinks.Remove(node.Link.YNode); node.Position.Y = y; node.Link.YNode = _yLinks.AddBefore(cur, node); break; } else if (cur.Previous == null) { _yLinks.Remove(node.Link.YNode); node.Position.Y = y; node.Link.YNode = _yLinks.AddAfter(cur, node); break; } cur = cur.Previous; } } } #endregion node.SetPosition(x, y); }
/// <summary> /// Move /// </summary> /// <param name="node"></param> /// <param name="target"></param> public void Move(AoiNode node, ref float target) { var cur = node; #region Left if (target > cur.Value) { while (cur != null) { if (cur.Right != null && target > cur.Right.Value) { var findNode = cur; // Find the target node to be moved to. while (findNode.Right != null && findNode.Right.Value < target) { findNode = findNode.Right; } // Fuse the current node. CircuitBreaker(cur); // Move to the target node location cur.Left = findNode; cur.Right = findNode.Right; if (findNode.Right != null) { findNode.Right.Left = cur; } findNode.Right = cur; } cur.Value = target; cur = cur.Top; } return; } #endregion #region Right while (cur != null) { if (cur.Left != null && target < cur.Left.Value) { // Find the target node to be moved to. var findNode = cur; while (findNode.Left != null && findNode.Left.Value > target) { findNode = findNode.Left; } // Fuse the current node. CircuitBreaker(cur); // Move to the target node location cur.Right = findNode; cur.Left = findNode.Left; if (findNode.Left != null) { findNode.Left.Right = cur; } findNode.Left = cur; } cur.Value = target; cur = cur.Top; } #endregion }
public void Move(ref AoiNode node, ref float target) { var cur = node; #region Left if (target > cur.Value) { if (cur.Right == null || target <= cur.Right.Value) { while (cur != null) { cur.Value = target; cur = cur.Top; } return; } while (cur != null) { var moveCur = cur; moveCur.Value = target; if (cur.Left != null || cur.Right != null) { if (cur.Right != null) { cur = cur.Right; } if (moveCur.Right != null) { moveCur.Right.Left = moveCur.Left; if (moveCur.Left != null) { moveCur.Left.Right = moveCur.Right; moveCur.Left = null; } moveCur.Right = null; } while (cur.Right != null && cur.Right.Value < target) { cur = cur.Right; } moveCur.Right = cur.Right; moveCur.Left = cur; if (cur.Right != null) { cur.Right.Left = moveCur; } cur.Right = moveCur; } cur = moveCur.Top; } return; } #endregion #region Right if (cur.Left == null || target >= cur.Left.Value) { while (cur != null) { cur.Value = target; cur = cur.Top; } return; } while (cur != null) { var moveCur = cur; moveCur.Value = target; if (cur.Left != null || cur.Right != null) { if (cur.Left != null) { cur = cur.Left; } if (moveCur.Left != null) { moveCur.Left.Right = moveCur.Right; if (moveCur.Right != null) { moveCur.Right.Left = moveCur.Left; moveCur.Right = null; } moveCur.Left = null; } while (cur.Left != null && cur.Left.Value > target) { cur = cur.Left; } moveCur.Left = cur.Left; moveCur.Right = cur; if (cur.Left != null) { cur.Left.Right = moveCur; } cur.Left = moveCur; } cur = moveCur.Top; } #endregion }
/// <summary> /// Move /// </summary> /// <param name="node"></param> /// <param name="target"></param> public void Move(AoiNode node, ref float target) { var cur = node; #region Left if (target > cur.Value) { while (cur != null) { if (cur.Right != null && target > cur.Right.Value) { var findNode = cur; // 寻找到需要移动到的目标节点。 while (findNode.Right != null && findNode.Right.Value < target) { findNode = findNode.Right; } // 熔断当前节点。 CircuitBreaker(cur); // 移动到目标节点位置 cur.Left = findNode; cur.Right = findNode.Right; if (findNode.Right != null) { findNode.Right.Left = cur; } findNode.Right = cur; } cur.Value = target; cur = cur.Top; } return; } #endregion #region Right while (cur != null) { if (cur.Left != null && target < cur.Left.Value) { // 寻找到需要移动到的目标节点。 var findNode = cur; while (findNode.Left != null && findNode.Left.Value > target) { findNode = findNode.Left; } // 熔断当前节点。 CircuitBreaker(cur); // 移动到目标节点位置。 cur.Right = findNode; cur.Left = findNode.Left; if (findNode.Left != null) { findNode.Left.Right = cur; } findNode.Left = cur; } cur.Value = target; cur = cur.Top; } #endregion }