/// <summary> /// Finds a path from any of the points in startPointList to goal, such that the path has no links that are steeper up than maxIncline /// nor steeper down than maxDecline. /// </summary> /// <returns>The path.</returns> /// <param name="startPointList">PointWithDistance structs for starting area</param> /// <param name="goalPoint">map indices of point to go to</param> List <PointWithDistance> FindPath(List <PointWithDistance> startPointList, InclineIndexPoint goalPoint, float maxIncline, float maxDecline) { List <PointWithDistance> path = new List <PointWithDistance>(); HeapQueue <PointWithDistance> openHeap = new HeapQueue <PointWithDistance>(); Dictionary <InclineIndexPoint, float> bestDistanceDict = new Dictionary <InclineIndexPoint, float>(); Dictionary <InclineIndexPoint, PointWithDistance> bestPrevPoint = new Dictionary <InclineIndexPoint, PointWithDistance>(); Point goalMapPoint = InclineIndicesToMapIndices(goalPoint); Vector3 worldGoalPoint = mapMetaData.getWorldPos(goalMapPoint); for (int startIndex = 0; startIndex < startPointList.Count; ++startIndex) { PointWithDistance pwd = startPointList[startIndex]; openHeap.Push(pwd); bestDistanceDict[pwd.point] = pwd.distance; bestPrevPoint[pwd.point] = null; } float bestPathLength = -1; PointWithDistance bestGoalPoint = new PointWithDistance(new InclineIndexPoint(-1024, -1024), float.MaxValue, float.MaxValue); while (!openHeap.IsEmpty()) { PointWithDistance ptWithDist = openHeap.PopMinimum(); if ((bestPathLength > 0) && ((ptWithDist.estimatedTotalDistance > bestPathLength) || TAKE_FIRST_PATH)) { break; } int[] xOffsets = { 1, 0, -1, 0 }; int[] zOffsets = { 0, 1, 0, -1 }; InclineMeshNode node = nodes[ptWithDist.point.X, ptWithDist.point.Z]; Vector3 worldNodePoint = InclineIndicesToWorldPoint(ptWithDist.point); for (int direction = 0; direction < 4; ++direction) { int dx = xOffsets[direction]; int dz = zOffsets[direction]; int nx = ptWithDist.point.X + dx; int nz = ptWithDist.point.Z + dz; InclineIndexPoint neighborPoint = new InclineIndexPoint(nx, nz); Point mapNeighborPoint = InclineIndicesToMapIndices(neighborPoint); if ((!mapMetaData.IsWithinBounds(mapNeighborPoint)) || (node.NeighborLinks[direction] == null)) { continue; } Vector3 worldNeighborPoint = InclineIndicesToWorldPoint(neighborPoint); for (int linkIndex = 0; linkIndex < node.NeighborLinks[direction].Count; ++linkIndex) { Debug.DrawLine(worldNodePoint, worldNeighborPoint, Color.yellow, 15.0f); InclineLinkData link = node.NeighborLinks[direction][linkIndex]; if ((link.declineAsFloat() > maxDecline) || (link.inclineAsFloat() > maxIncline)) { continue; } float linkDistance = (worldNeighborPoint - worldNodePoint).magnitude; float totalDistance = ptWithDist.distance + linkDistance; if ((bestPathLength >= 0) && (totalDistance >= bestPathLength)) { continue; } if ((!bestDistanceDict.ContainsKey(neighborPoint)) || (totalDistance < bestDistanceDict[neighborPoint])) { bestDistanceDict[neighborPoint] = totalDistance; bestPrevPoint[neighborPoint] = ptWithDist; float distanceToGoal = (worldNeighborPoint - worldGoalPoint).magnitude; if (neighborPoint.Equals(goalPoint)) { if ((bestPathLength < 0) || (totalDistance < bestPathLength)) { bestPathLength = totalDistance; bestGoalPoint = new PointWithDistance(neighborPoint, totalDistance, 0.0f); } } else { openHeap.Push(new PointWithDistance(neighborPoint, totalDistance, totalDistance + distanceToGoal)); } } break; } } } if (bestPathLength >= 0) { PointWithDistance p = bestGoalPoint; path.Add(p); while (bestPrevPoint.ContainsKey(p.point)) { PointWithDistance prevPoint = bestPrevPoint[p.point]; if ((prevPoint == null) || (path.Contains(prevPoint))) { break; } path.Insert(0, prevPoint); p = prevPoint; } } return(path); }
public bool LoadFromPath(string path) { FileStream fileStream = null; try { fileStream = new FileStream(path, FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fileStream); // read here int sizeX = br.ReadInt32(); if (sizeX <= 0) { Debug.LogErrorFormat("Error loading incline mesh {0}, sizeX == {1}", path, sizeX); return(false); } int sizeZ = br.ReadInt32(); if (sizeZ <= 0) { Debug.LogErrorFormat("Error loading incline mesh {0}, sizeX == {1}", path, sizeZ); return(false); } this.downsampleFactor = br.ReadInt32(); if (downsampleFactor <= 0) { Debug.LogErrorFormat("Error loading incline mesh {0}, downsampleFactor == {1}", path, downsampleFactor); return(false); } this.sizeX = sizeX; this.sizeZ = sizeZ; this.nodes = new InclineMeshNode[sizeX, sizeZ]; for (int x = 0; x < sizeX; ++x) { for (int z = 0; z < sizeZ; ++z) { bool hasNode = br.ReadBoolean(); if (!hasNode) { nodes[x, z] = null; } else { InclineMeshNode node = new InclineMeshNode(); nodes[x, z] = node; node.Read(br); } } } } catch (System.IO.IsolatedStorage.IsolatedStorageException ise) { Debug.LogWarningFormat("IsolatedStorageException {0}, could not find {1}. This will cripple the AI.", ise.Message, path); return(false); } catch (FileNotFoundException e) { Debug.LogWarningFormat("Could not find {0}. This will cripple the AI.", e.FileName); return(false); } finally { if (fileStream != null) { fileStream.Dispose(); } } return(true); }