//获取P点四周为的可以通过的点 public static Vector2Int?FindAroundFreePoint(AStarMapPath astarMapPath, Vector2Int basePoint, List <Vector2Int> exceptPointList, int[] canPassObstacleTypes, int[] canPassTerrainTypes, RandomManager randomManager = null) { randomManager = randomManager ?? Client.instance.randomManager; if (!IsInRange(astarMapPath.GetFinalGrids(), basePoint)) { return(null); } if (CanPass(astarMapPath, basePoint.x, basePoint.y, canPassObstacleTypes, canPassTerrainTypes) && (exceptPointList == null || !exceptPointList.Contains(basePoint))) { return(basePoint); } int max = Math.Max(Math.Max(basePoint.x, astarMapPath.Width() - basePoint.x), Math.Max(basePoint.y, astarMapPath.Height() - basePoint.y)); for (int i = 1; i <= max; i++) { List <Vector2Int> list = GetAroundFreePointList(astarMapPath, basePoint, i, canPassObstacleTypes, canPassTerrainTypes); if (exceptPointList != null) { list.RemoveElementsOfSub(exceptPointList); } if (list.Count > 0) { return(list[randomManager.RandomInt(0, list.Count)]); } } return(null); }
//获取range范围内的可以通过的格子列表 public static List <Vector2Int> GetRangeFreePointList(AStarMapPath astarMapPath, int x1, int y1, int x2, int y2, List <Vector2Int> exceptPointList, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { List <Vector2Int> list = new List <Vector2Int>(); for (int x = x1; x <= x2; x++) { for (int y = y1; y <= y2; y++) { if (!IsInRange(astarMapPath.GetFinalGrids(), x, y)) { continue; } bool canPass = CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes); if (canPass) { Vector2Int p = new Vector2Int(x, y); if (exceptPointList == null || !exceptPointList.Contains(p)) { list.Add(p); } } } } return(list); }
public static void Test2() { int[][] grids = new AStarMapPath(StdioUtil.ReadTextFile("E:/WorkSpace/Unity/Test/Assets/tile/tileSet/fff.txt")) .grids; LogCat.log(grids); }
// 设置子场景投影障碍到主场景(仅供父级场景调用) public void SetProjectGrids(Vector2Int baseOnParentPos, Scene child_scene) { CheckParentCall(); AStarMapPath mapPath = GetMapPath(); if (mapPath == null || mapPath.grids == null) { return; } int[][] projectGrids; projectGrids = child_scene.GetMapType() == 1 ? child_scene.GetGrids() : child_scene.GetProjectGrids(); if (projectGrids != null) { Vector2Int offsetPos = child_scene.GetOffsetPos(); for (int x = 0; x < projectGrids.Length; x++) { for (int y = 0; y < projectGrids[x].Length; y++) { int v = projectGrids[x][y]; if (v == 0 || !AStarUtil.IsValidObstacleType(v)) // 子场景无效区域不投影 { continue; } int px = ToParentX(baseOnParentPos, offsetPos, x); int py = ToParentY(baseOnParentPos, offsetPos, y); if (mapPath.IsValidPoint(px, py)) // 父场景无效区域不投影 { mapPath.projectGrids[px][py] = v; } } } } }
protected int[] canPassTerrainTypes; // 可通过地形表 public AStarImpl(AStarMapPath astarMapPath, AStarHType astarHType, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { this.astarMapPath = astarMapPath; SetAStarHType(astarHType); SetCanPassType(canPassObstacleTypes, canPassTerrainTypes); SetRange(0, 0, astarMapPath.Height() - 1, astarMapPath.Width() - 1); }
//更新路径信息 public void UpdateMapPath() { SceneMapInfo sceneMapInfo = GetSceneMapInfo(); if (sceneMapInfo != null) { AStarMapPath mapPath = new AStarMapPath(sceneMapInfo.grids); SetTmp("mapPath", mapPath); } }
//获得两点间可通过的最远点 // can_out 是否允许通过场景外 public static Vector2Int GetMostLinePassPoint(AStarMapPath astarMapPath, Vector2Int lp, Vector2Int tp, int[] canPassObstacleTypes, int[] canPassTerrainTypes, bool canOut = false) { if (!canOut && !IsInRange(astarMapPath.GetFinalGrids(), lp)) { return(lp); } List <Vector2Int> pointList = GetLinePointList(lp, tp); return(GetMostPassPoint(astarMapPath, pointList, canPassObstacleTypes, canPassTerrainTypes, canOut)); }
//检测两点间直线是否可通过 public static bool CanLinePass(AStarMapPath astarMapPath, Vector2Int pointA, Vector2Int pointB, int[] canPassObstacleTypes, int[] canPassTerrainTypes, bool canOut = false) { if (!canOut && (!IsInRange(astarMapPath.GetFinalGrids(), pointA) || !IsInRange(astarMapPath.GetFinalGrids(), pointB))) { return(false); } var linePointList = GetLinePointList(pointA, pointB); return(CanPass(astarMapPath, linePointList, canPassObstacleTypes, canPassTerrainTypes, canOut)); }
//获取离a,b最近的点 public static Vector2Int GetNearestPoint(AStarMapPath astarMapPath, Vector2Int pointA, Vector2Int pointB, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { Vector2Int p = pointA; do { if (!p.Equals(pointA)) { pointA = p; } p = GetNearestNearbyPoint(astarMapPath, pointA, pointB, canPassObstacleTypes, canPassTerrainTypes); } while (!p.Equals(pointA)); return(p); }
//清空所有动态障碍(仅供父级场景调用) public void ClearAllProjectGrids() { CheckParentCall(); AStarMapPath mapPath = GetMapPath(); if (mapPath == null || mapPath.projectGrids == null) { return; } for (int x = 0; x < mapPath.projectGrids.Length; x++) { for (int y = 0; y < mapPath.projectGrids[x].Length; y++) { mapPath.projectGrids[x][y] = 0; } } }
//获取P点四周为+-out_count的可以通过的点 public static Vector2Int?FindAroundFreePoint(AStarMapPath astarMapPath, Vector2Int basePoint, int outCount, int[] canPassObstacleTypes, int[] canPassTerrainTypes, RandomManager randomManager = null) { randomManager = randomManager ?? Client.instance.randomManager; if (!IsInRange(astarMapPath.GetFinalGrids(), basePoint)) { return(null); } List <Vector2Int> list = GetAroundFreePointList(astarMapPath, basePoint, outCount, canPassObstacleTypes, canPassTerrainTypes); if (list.Count > 0) { return(list[randomManager.RandomInt(0, list.Count)]); } return(null); }
//检测某个点是否可通过 // can_out 是否允许在场景外 public static bool CanPass(AStarMapPath astarMapPath, int x, int y, int[] canPassObstacleTypes, int[] canPassTerrainTypes, bool canOut = false) { if (!IsInRange(astarMapPath.GetFinalGrids(), x, y)) { return(canOut); } int grid_type = astarMapPath.GetFinalGrids()[x][y]; // 固有地形+障碍 if (!IsValidObstacleType(grid_type)) // 填充区域 { return(canOut); } if (!CanPass(astarMapPath.GetFinalGrids(), x, y, canPassObstacleTypes, canPassTerrainTypes)) { return(false); } return(true); }
//获取range范围内的可以通过的格子 public static Vector2Int?FindRangeFreePoint(AStarMapPath astarMapPath, int x1, int y1, int x2, int y2, List <Vector2Int> exceptPointList, int[] canPassObstacleTypes, int[] canPassTerrainTypes, RandomManager randomManager = null) { randomManager = randomManager ?? Client.instance.randomManager; List <Vector2Int> list = GetRangeFreePointList(astarMapPath, x1, y1, x2, y2, exceptPointList, canPassObstacleTypes, canPassTerrainTypes); if (exceptPointList != null) { list.RemoveElementsOfSub(exceptPointList); } if (list.Count > 0) { return(list[randomManager.RandomInt(0, list.Count)]); } return(null); }
public static Vector2Int?GetRandomMovePoint(AStarMapPath astarMapPath, Vector2Int basePoint, Vector2Int goalPoint, int maxRadiusBetweenTargetPointAndGoalPoint, int[] canPassObstacleTypes, int[] canPassTerrainTypes, RandomManager randomManager = null) { randomManager = randomManager ?? Client.instance.randomManager; int outCount = randomManager.RandomInt(AStarMapPathConst.Random_Move_Distance_Min, AStarMapPathConst.Random_Move_Distance_Max + 1); List <Vector2Int> list = GetAroundFreePointList(astarMapPath, basePoint, outCount, canPassObstacleTypes, canPassTerrainTypes); while (list.Count > 0) { int removeIndex = randomManager.RandomInt(0, list.Count); Vector2Int targetPoint = list[removeIndex]; list.RemoveAt(removeIndex); if (Vector2Int.Distance(goalPoint, targetPoint) <= maxRadiusBetweenTargetPointAndGoalPoint) { return(targetPoint); } } return(null); }
//直角寻路(先横向再纵向寻路) public static List <Vector2Int> BorderFindPath(AStarMapPath astarMapPath, Vector2Int pointA, Vector2Int pointB, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { if (!AStarUtil.IsInRange(astarMapPath.GetFinalGrids(), pointA) || !AStarUtil.IsInRange(astarMapPath.GetFinalGrids(), pointB)) { return(null); } List <Vector2Int> list = new List <Vector2Int> { pointA }; int dv = pointB.x > pointA.x ? 1 : -1; for (int x = pointA.x + dv; x *dv <= pointB.x *dv; x += dv) { // LogCat.log(x, point_a.y); if (!AStarUtil.CanPass(astarMapPath, x, pointA.y, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } list.Add(new Vector2Int(x, pointA.y)); } dv = pointB.y > pointA.y ? 1 : -1; for (int y = pointA.y + dv; y *dv < pointB.y *dv; y += dv) { if (!AStarUtil.CanPass(astarMapPath, pointB.x, y, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } list.Add(new Vector2Int(pointB.x, y)); } list.Add(pointB); return(list); }
//对角线寻路 public static List <Vector2Int> DiagonallyFindPath(AStarMapPath astarMapPath, Vector2Int pointA, Vector2Int pointB, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { if (!AStarUtil.IsInRange(astarMapPath.GetFinalGrids(), pointA) || !AStarUtil.IsInRange(astarMapPath.GetFinalGrids(), pointB)) { return(null); } List <Vector2Int> list = new List <Vector2Int>(); int dx = pointB.x - pointA.x; int dy = pointB.y - pointA.y; if (Math.Abs(dx) > Math.Abs(dy)) { int x1; if (dx > 0) { x1 = pointA.x + Math.Abs(dy); } else { x1 = pointA.x - Math.Abs(dy); } Vector2Int p = new Vector2Int(x1, pointB.y); if (!AStarUtil.CanPass(astarMapPath, p.x, p.y, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } List <Vector2Int> list1 = AStarUtil.GetLinePointList(pointA, p); if (!AStarUtil.CanPass(astarMapPath, list1, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } List <Vector2Int> list2 = AStarUtil.GetLinePointList(p, pointB); if (!AStarUtil.CanPass(astarMapPath, list2, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } list.AddRange(list1); list.RemoveLast(); //删掉p list.AddRange(list2); } else { int y1; if (dy > 0) { y1 = pointA.y + Math.Abs(dx); } else { y1 = pointA.y - Math.Abs(dx); } Vector2Int p = new Vector2Int(pointB.x, y1); if (!AStarUtil.CanPass(astarMapPath, p.x, p.y, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } List <Vector2Int> list1 = AStarUtil.GetLinePointList(pointA, p); if (!AStarUtil.CanPass(astarMapPath, list1, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } List <Vector2Int> list2 = AStarUtil.GetLinePointList(p, pointB); if (!AStarUtil.CanPass(astarMapPath, list2, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } list.AddRange(list1); list.RemoveLast(); //删掉p list.AddRange(list2); } return(list); }
//先对角线查找,再直角查找 public static List <Vector2Int> DirectFindPath(AStarMapPath astarMapPath, Vector2Int pointA, Vector2Int pointB, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { if (!AStarUtil.IsInRange(astarMapPath.GetFinalGrids(), pointA) || !AStarUtil.IsInRange(astarMapPath.GetFinalGrids(), pointB)) { return(null); } List <Vector2Int> list = null; if (pointA.Equals(pointB)) // 同一点 { list = new List <Vector2Int> { pointA }; } else if (pointA.x == pointB.x) { list = new List <Vector2Int> { pointA }; int dv = pointB.y > pointA.y ? 1 : -1; for (int y = pointA.y + dv; y *dv < pointB.y *dv; y += dv) { if (!AStarUtil.CanPass(astarMapPath, pointA.x, y, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } list.Add(new Vector2Int(pointA.x, y)); } list.Add(pointB); } else if (pointA.y == pointB.y) { list = new List <Vector2Int> { pointA }; int dv = pointB.x > pointA.x ? 1 : -1; for (int x = pointA.x + dv; x *dv < pointB.x *dv; x += dv) { if (!AStarUtil.CanPass(astarMapPath, x, pointA.y, canPassObstacleTypes, canPassTerrainTypes)) { return(null); } list.Add(new Vector2Int(x, pointA.y)); } list.Add(pointB); } else { //先对角线查找,再直角查找 list = DiagonallyFindPath(astarMapPath, pointA, pointB, canPassObstacleTypes, canPassTerrainTypes); if (list == null) { list = DiagonallyFindPath(astarMapPath, pointB, pointA, canPassObstacleTypes, canPassTerrainTypes); if (list == null) { list = BorderFindPath(astarMapPath, pointA, pointB, canPassObstacleTypes, canPassTerrainTypes); if (list == null) { list = BorderFindPath(astarMapPath, pointB, pointA, canPassObstacleTypes, canPassTerrainTypes); list?.Reverse(); } } else { list.Reverse(); } } } return(list); }
//获取P点四周为+-out_count的可以通过的点列表 public static List <Vector2Int> GetAroundFreePointList(AStarMapPath astarMapPath, Vector2Int basePoint, int outCount, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { List <Vector2Int> list = new List <Vector2Int>(); int x, y; int field = GetField(astarMapPath.GetFinalGrids()[basePoint.x][basePoint.y]); // 所属区块值 bool canPass = CanPass(astarMapPath, basePoint.x, basePoint.y, canPassObstacleTypes, canPassTerrainTypes); // 是否起始在障碍点 y = basePoint.y - outCount; // 下边一行 if (IsInRangeY(astarMapPath.GetFinalGrids(), y)) { for (x = basePoint.x - outCount; x <= basePoint.x + outCount; x++) { if (IsInRange(astarMapPath.GetFinalGrids(), x, y) && (!canPass || field == GetField(astarMapPath.GetFinalGrids()[x][y])) && CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes)) { list.Add(new Vector2Int(x, y)); } } } x = basePoint.x + outCount; // 右边一行 if (IsInRangeX(astarMapPath.GetFinalGrids(), x)) { for (y = basePoint.y - outCount; y <= basePoint.y + outCount; y++) { if (IsInRange(astarMapPath.GetFinalGrids(), x, y) && (!canPass || field == GetField(astarMapPath.GetFinalGrids()[x][y])) && CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes)) { list.Add(new Vector2Int(x, y)); } } } y = basePoint.y + outCount; // 上边一行 if (IsInRangeY(astarMapPath.GetFinalGrids(), y)) { for (x = basePoint.x + outCount; x >= basePoint.x - outCount; x--) { if (IsInRange(astarMapPath.GetFinalGrids(), x, y) && (!canPass || field == GetField(astarMapPath.GetFinalGrids()[x][y])) && CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes)) { list.Add(new Vector2Int(x, y)); } } } x = basePoint.x - outCount; // 左边一行 if (IsInRangeX(astarMapPath.GetFinalGrids(), x)) { for (y = basePoint.y + outCount; y >= basePoint.y - outCount; y--) { if (IsInRange(astarMapPath.GetFinalGrids(), x, y) && (!canPass || field == GetField(astarMapPath.GetFinalGrids()[x][y])) && CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes)) { list.Add(new Vector2Int(x, y)); } } } return(list); }
//获取range范围内的可以通过的格子 public static Vector2Int?FindRangeFreePoint(AStarMapPath astarMapPath, int x1, int y1, int x2, int y2, int[] canPassObstacleTypes, int[] canPassTerrainTypes, RandomManager randomManager = null) { return(FindRangeFreePoint(astarMapPath, x1, y1, x2, y2, null, canPassObstacleTypes, canPassTerrainTypes, randomManager)); }
private static Vector2Int GetNearestNearbyPoint(AStarMapPath astarMapPath, Vector2Int pointA, Vector2Int pointB, int[] canPassObstacleTypes, int[] canPassTerrainTypes) { int dx = pointB.x > pointA.x ? 1 : pointB.x < pointA.x ? -1 : 0; int dy = pointB.y > pointA.y ? 1 : pointB.y < pointA.y ? -1 : 0; int minDistance = GetMapDistance(pointA, pointB); Vector2Int minPoint = pointA; int x, y; x = pointA.x + dx; y = pointA.y; bool s1 = false; if (IsInRange(astarMapPath.GetFinalGrids(), x, y)) { Vector2Int p = new Vector2Int(x, y); if (CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes)) { s1 = true; int d = GetMapDistance(p, pointB); if (d < minDistance) { minPoint = p; minDistance = d; } } } x = pointA.x; y = pointA.y + dy; bool s2 = false; if (IsInRange(astarMapPath.GetFinalGrids(), x, y)) { Vector2Int p = new Vector2Int(x, y); if (CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes)) { s2 = true; int d = GetMapDistance(p, pointB); if (d < minDistance) { minPoint = p; minDistance = d; } } } if (s1 || s2) { x = pointA.x + dx; y = pointA.y + dy; if (IsInRange(astarMapPath.GetFinalGrids(), x, y)) { Vector2Int p = new Vector2Int(x, y); if (CanPass(astarMapPath, x, y, canPassObstacleTypes, canPassTerrainTypes)) { int d = GetMapDistance(p, pointB); if (d < minDistance) { minPoint = p; minDistance = d; } } } } return(minPoint); }
//获得轨迹中可通过的最远点 public static Vector2Int GetMostPassPoint(AStarMapPath astarMapPath, List <Vector2Int> trackList, int[] canPassObstacleTypes, int[] canPassTerrainTypes, bool canOut = false) { Vector2Int lp = trackList[0]; Vector2Int tp = lp; for (int i = 1; i < trackList.Count; i++) { Vector2Int p = trackList[i]; if (!CanPass(astarMapPath, p.x, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } DirectionInfo directionInfo = DirectionInfoUtil.GetDirectionInfo(p.x - lp.x, p.y - lp.y); // directionInfo = DirectionConst.GetDirectionInfo(0, 0); // 不再判断临边障碍 2012-10-29 // LogCat.log(directionInfo.name); if (directionInfo == DirectionInfoConst.LeftTopDirectionInfo) // 左上角 { if (!CanPass(astarMapPath, p.x + 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } if (!CanPass(astarMapPath, p.x, p.y - 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } } else if (directionInfo == DirectionInfoConst.RightTopDirectionInfo) // 右上角 { if (!CanPass(astarMapPath, p.x - 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } if (!CanPass(astarMapPath, p.x, p.y - 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } } else if (directionInfo == DirectionInfoConst.RightBottomDirectionInfo) // 右下角 { if (!CanPass(astarMapPath, p.x - 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } if (!CanPass(astarMapPath, p.x, p.y + 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } } else if (directionInfo == DirectionInfoConst.LeftBottomDirectionInfo) // 左下角 { if (!CanPass(astarMapPath, p.x + 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } if (!CanPass(astarMapPath, p.x, p.y + 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { break; } } lp = p; tp = lp; } return(tp); }
//检测轨迹是否可通过 // can_out 是否允许在场景外 public static bool CanPass(AStarMapPath astarMapPath, List <Vector2Int> trackList, int[] canPassObstacleTypes, int[] canPassTerrainTypes, bool canOut = false) { if (trackList.Count == 0) { return(true); } Vector2Int lp = trackList[0]; if (trackList.Count == 1) { return(CanPass(astarMapPath, lp.x, lp.y, canPassObstacleTypes, canPassTerrainTypes, canOut)); } for (int i = 1; i < trackList.Count; i++) { Vector2Int p = trackList[i]; if (!CanPass(astarMapPath, p.x, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } DirectionInfo directionInfo = DirectionInfoUtil.GetDirectionInfo(p.x - lp.x, p.y - lp.y); // directionInfo = DirectionConst.GetDirectionInfo(0, 0); if (directionInfo == DirectionInfoConst.LeftTopDirectionInfo) // 左上角 { if (!CanPass(astarMapPath, p.x + 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } if (!CanPass(astarMapPath, p.x, p.y - 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } } else if (directionInfo == DirectionInfoConst.RightTopDirectionInfo) // 右上角 { if (!CanPass(astarMapPath, p.x - 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } if (!CanPass(astarMapPath, p.x, p.y - 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } } else if (directionInfo == DirectionInfoConst.RightBottomDirectionInfo) // 右下角 { if (!CanPass(astarMapPath, p.x - 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } if (!CanPass(astarMapPath, p.x, p.y + 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } } else if (directionInfo == DirectionInfoConst.LeftBottomDirectionInfo) // 左下角 { if (!CanPass(astarMapPath, p.x + 1, p.y, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } if (!CanPass(astarMapPath, p.x, p.y + 1, canPassObstacleTypes, canPassTerrainTypes, canOut)) { return(false); } } lp = p; } return(true); }