private static void identifySuccessors(JumpPointParam iParam, Node iNode) { HeuristicDelegate tHeuristic = iParam.HeuristicFunc; List <Node> tOpenList = iParam.openList; int tEndX = iParam.EndNode.x; int tEndY = iParam.EndNode.y; LPoint tNeighbor; LPoint?tJumpPoint; Node tJumpNode; List <LPoint> tNeighbors = findNeighbors(iParam, iNode); for (int i = 0; i < tNeighbors.Count; i++) { tNeighbor = tNeighbors[i]; if (iParam.UseRecursive) { tJumpPoint = jump(iParam, tNeighbor.x, tNeighbor.y, iNode.x, iNode.y); } else { tJumpPoint = jumpLoop(iParam, tNeighbor.x, tNeighbor.y, iNode.x, iNode.y); } if (tJumpPoint != null) { tJumpNode = iParam.SearchGrid.GetNodeAt(tJumpPoint.Value.x, tJumpPoint.Value.y); if (tJumpNode == null) { if (iParam.EndNode.x == tJumpPoint.Value.x && iParam.EndNode.y == tJumpPoint.Value.y) { tJumpNode = iParam.SearchGrid.GetNodeAt(tJumpPoint.Value); } } if (tJumpNode.isClosed) { continue; } // include distance, as parent may not be immediately adjacent: float tCurNodeToJumpNodeLen = tHeuristic(Math.Abs(tJumpPoint.Value.x - iNode.x), Math.Abs(tJumpPoint.Value.y - iNode.y)); float tStartToJumpNodeLen = iNode.startToCurNodeLen + tCurNodeToJumpNodeLen; // next `startToCurNodeLen` value if (!tJumpNode.isOpened || tStartToJumpNodeLen < tJumpNode.startToCurNodeLen) { tJumpNode.startToCurNodeLen = tStartToJumpNodeLen; tJumpNode.heuristicCurNodeToEndLen = (tJumpNode.heuristicCurNodeToEndLen == null ? tHeuristic(Math.Abs(tJumpPoint.Value.x - tEndX), Math.Abs(tJumpPoint.Value.y - tEndY)) : tJumpNode.heuristicCurNodeToEndLen); tJumpNode.heuristicStartToEndLen = tJumpNode.startToCurNodeLen + tJumpNode.heuristicCurNodeToEndLen.Value; tJumpNode.parent = iNode; if (!tJumpNode.isOpened) { tOpenList.Add(tJumpNode); tJumpNode.isOpened = true; } } } } }
public static List <LPoint> FindPath(JumpPointParam iParam) { List <Node> tOpenList = iParam.openList; Node tStartNode = iParam.StartNode; Node tEndNode = iParam.EndNode; Node tNode; bool revertEndNodeWalkable = false; // set the `g` and `f` value of the start node to be 0 tStartNode.startToCurNodeLen = 0; tStartNode.heuristicStartToEndLen = 0; // push the start node into the open list tOpenList.Add(tStartNode); tStartNode.isOpened = true; if (iParam.AllowEndNodeUnWalkable && !iParam.SearchGrid.IsWalkableAt(tEndNode.x, tEndNode.y)) { iParam.SearchGrid.SetWalkableAt(tEndNode.x, tEndNode.y, true); revertEndNodeWalkable = true; } // while the open list is not empty while (tOpenList.Count > 0) { // pop the position of node which has the minimum `f` value. tOpenList.Sort(); tNode = (Node)tOpenList[tOpenList.Count - 1]; tOpenList.RemoveAt(tOpenList.Count - 1); tNode.isClosed = true; if (tNode.Equals(tEndNode)) { if (revertEndNodeWalkable) { iParam.SearchGrid.SetWalkableAt(tEndNode.x, tEndNode.y, false); } return(Node.Backtrace(tNode)); // rebuilding path } identifySuccessors(iParam, tNode); } if (revertEndNodeWalkable) { iParam.SearchGrid.SetWalkableAt(tEndNode.x, tEndNode.y, false); } // fail to find the path return(new List <LPoint>()); }
public JumpPointParam(JumpPointParam b) { m_heuristic = b.m_heuristic; m_allowEndNodeUnWalkable = b.m_allowEndNodeUnWalkable; m_crossAdjacentPoint = b.m_crossAdjacentPoint; m_crossCorner = b.m_crossCorner; openList = new List <Node>(b.openList); m_searchGrid = b.m_searchGrid; m_startNode = b.m_startNode; m_endNode = b.m_endNode; m_useRecursive = b.m_useRecursive; }
private static List <LPoint> findNeighbors(JumpPointParam iParam, Node iNode) { Node tParent = (Node)iNode.parent; int tX = iNode.x; int tY = iNode.y; int tPx, tPy, tDx, tDy; List <LPoint> tNeighbors = new List <LPoint>(); List <Node> tNeighborNodes; Node tNeighborNode; // directed pruning: can ignore most neighbors, unless forced. if (tParent != null) { tPx = tParent.x; tPy = tParent.y; // get the normalized direction of travel tDx = (tX - tPx) / Math.Max(Math.Abs(tX - tPx), 1); tDy = (tY - tPy) / Math.Max(Math.Abs(tY - tPy), 1); if (iParam.CrossCorner) { // search diagonally if (tDx != 0 && tDy != 0) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy)) { tNeighbors.Add(new LPoint(tX, tY + tDy)); } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY)) { tNeighbors.Add(new LPoint(tX + tDx, tY)); } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY + tDy)) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy) || iParam.SearchGrid.IsWalkableAt(tX + tDx, tY)) { tNeighbors.Add(new LPoint(tX + tDx, tY + tDy)); } else if (iParam.CrossAdjacentPoint) { tNeighbors.Add(new LPoint(tX + tDx, tY + tDy)); } } if (iParam.SearchGrid.IsWalkableAt(tX - tDx, tY + tDy)) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy) && !iParam.SearchGrid.IsWalkableAt(tX - tDx, tY)) { tNeighbors.Add(new LPoint(tX - tDx, tY + tDy)); } else if (iParam.CrossAdjacentPoint) { tNeighbors.Add(new LPoint(tX - tDx, tY + tDy)); } } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - tDy)) { if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY) && !iParam.SearchGrid.IsWalkableAt(tX, tY - tDy)) { tNeighbors.Add(new LPoint(tX + tDx, tY - tDy)); } else if (iParam.CrossAdjacentPoint) { tNeighbors.Add(new LPoint(tX + tDx, tY - tDy)); } } } // search horizontally/vertically else { if (tDx == 0) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy)) { tNeighbors.Add(new LPoint(tX, tY + tDy)); if (iParam.SearchGrid.IsWalkableAt(tX + 1, tY + tDy) && !iParam.SearchGrid.IsWalkableAt(tX + 1, tY)) { tNeighbors.Add(new LPoint(tX + 1, tY + tDy)); } if (iParam.SearchGrid.IsWalkableAt(tX - 1, tY + tDy) && !iParam.SearchGrid.IsWalkableAt(tX - 1, tY)) { tNeighbors.Add(new LPoint(tX - 1, tY + tDy)); } } else if (iParam.CrossAdjacentPoint) { if (iParam.SearchGrid.IsWalkableAt(tX + 1, tY + tDy) && !iParam.SearchGrid.IsWalkableAt(tX + 1, tY)) { tNeighbors.Add(new LPoint(tX + 1, tY + tDy)); } if (iParam.SearchGrid.IsWalkableAt(tX - 1, tY + tDy) && !iParam.SearchGrid.IsWalkableAt(tX - 1, tY)) { tNeighbors.Add(new LPoint(tX - 1, tY + tDy)); } } } else { if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY)) { tNeighbors.Add(new LPoint(tX + tDx, tY)); if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY + 1) && !iParam.SearchGrid.IsWalkableAt(tX, tY + 1)) { tNeighbors.Add(new LPoint(tX + tDx, tY + 1)); } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - 1) && !iParam.SearchGrid.IsWalkableAt(tX, tY - 1)) { tNeighbors.Add(new LPoint(tX + tDx, tY - 1)); } } else if (iParam.CrossAdjacentPoint) { if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY + 1) && !iParam.SearchGrid.IsWalkableAt(tX, tY + 1)) { tNeighbors.Add(new LPoint(tX + tDx, tY + 1)); } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - 1) && !iParam.SearchGrid.IsWalkableAt(tX, tY - 1)) { tNeighbors.Add(new LPoint(tX + tDx, tY - 1)); } } } } } else // if(!iParam.CrossCorner) { // search diagonally if (tDx != 0 && tDy != 0) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy)) { tNeighbors.Add(new LPoint(tX, tY + tDy)); } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY)) { tNeighbors.Add(new LPoint(tX + tDx, tY)); } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY + tDy)) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX + tDx, tY)) { tNeighbors.Add(new LPoint(tX + tDx, tY + tDy)); } } if (iParam.SearchGrid.IsWalkableAt(tX - tDx, tY + tDy)) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX - tDx, tY)) { tNeighbors.Add(new LPoint(tX - tDx, tY + tDy)); } } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - tDy)) { if (iParam.SearchGrid.IsWalkableAt(tX, tY - tDy) && iParam.SearchGrid.IsWalkableAt(tX + tDx, tY)) { tNeighbors.Add(new LPoint(tX + tDx, tY - tDy)); } } } // search horizontally/vertically else { if (tDx == 0) { if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy)) { tNeighbors.Add(new LPoint(tX, tY + tDy)); if (iParam.SearchGrid.IsWalkableAt(tX + 1, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX + 1, tY)) { tNeighbors.Add(new LPoint(tX + 1, tY + tDy)); } if (iParam.SearchGrid.IsWalkableAt(tX - 1, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX - 1, tY)) { tNeighbors.Add(new LPoint(tX - 1, tY + tDy)); } } if (iParam.SearchGrid.IsWalkableAt(tX + 1, tY)) { tNeighbors.Add(new LPoint(tX + 1, tY)); } if (iParam.SearchGrid.IsWalkableAt(tX - 1, tY)) { tNeighbors.Add(new LPoint(tX - 1, tY)); } } else { if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY)) { tNeighbors.Add(new LPoint(tX + tDx, tY)); if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY + 1) && iParam.SearchGrid.IsWalkableAt(tX, tY + 1)) { tNeighbors.Add(new LPoint(tX + tDx, tY + 1)); } if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - 1) && iParam.SearchGrid.IsWalkableAt(tX, tY - 1)) { tNeighbors.Add(new LPoint(tX + tDx, tY - 1)); } } if (iParam.SearchGrid.IsWalkableAt(tX, tY + 1)) { tNeighbors.Add(new LPoint(tX, tY + 1)); } if (iParam.SearchGrid.IsWalkableAt(tX, tY - 1)) { tNeighbors.Add(new LPoint(tX, tY - 1)); } } } } } // return all neighbors else { tNeighborNodes = iParam.SearchGrid.GetNeighbors(iNode, iParam.CrossCorner, iParam.CrossAdjacentPoint); for (int i = 0; i < tNeighborNodes.Count; i++) { tNeighborNode = tNeighborNodes[i]; tNeighbors.Add(new LPoint(tNeighborNode.x, tNeighborNode.y)); } } return(tNeighbors); }
private static LPoint?jump(JumpPointParam iParam, int iX, int iY, int iPx, int iPy) { if (!iParam.SearchGrid.IsWalkableAt(iX, iY)) { return(null); } else if (iParam.SearchGrid.GetNodeAt(iX, iY).Equals(iParam.EndNode)) { return(new LPoint(iX, iY)); } int tDx = iX - iPx; int tDy = iY - iPy; LPoint?jx = null; LPoint?jy = null; if (iParam.CrossCorner) { // check for forced neighbors // along the diagonal if (tDx != 0 && tDy != 0) { if ((iParam.SearchGrid.IsWalkableAt(iX - tDx, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX - tDx, iY)) || (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY - tDy) && !iParam.SearchGrid.IsWalkableAt(iX, iY - tDy))) { return(new LPoint(iX, iY)); } } // horizontally/vertically else { if (tDx != 0) { // moving along x if ((iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + 1) && !iParam.SearchGrid.IsWalkableAt(iX, iY + 1)) || (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY - 1) && !iParam.SearchGrid.IsWalkableAt(iX, iY - 1))) { return(new LPoint(iX, iY)); } } else { if ((iParam.SearchGrid.IsWalkableAt(iX + 1, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX + 1, iY)) || (iParam.SearchGrid.IsWalkableAt(iX - 1, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX - 1, iY))) { return(new LPoint(iX, iY)); } } } // when moving diagonally, must check for vertical/horizontal jump points if (tDx != 0 && tDy != 0) { jx = jump(iParam, iX + tDx, iY, iX, iY); jy = jump(iParam, iX, iY + tDy, iX, iY); if (jx != null || jy != null) { return(new LPoint(iX, iY)); } } // moving diagonally, must make sure one of the vertical/horizontal // neighbors is open to allow the path if (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY) || iParam.SearchGrid.IsWalkableAt(iX, iY + tDy)) { return(jump(iParam, iX + tDx, iY + tDy, iX, iY)); } else if (iParam.CrossAdjacentPoint) { return(jump(iParam, iX + tDx, iY + tDy, iX, iY)); } else { return(null); } } else //if (!iParam.CrossCorner) { // check for forced neighbors // along the diagonal if (tDx != 0 && tDy != 0) { if ((iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + tDy) && iParam.SearchGrid.IsWalkableAt(iX, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX + tDx, iY)) || (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + tDy) && iParam.SearchGrid.IsWalkableAt(iX + tDx, iY) && !iParam.SearchGrid.IsWalkableAt(iX, iY + tDy))) { return(new LPoint(iX, iY)); } } // horizontally/vertically else { if (tDx != 0) { // moving along x if ((iParam.SearchGrid.IsWalkableAt(iX, iY + 1) && !iParam.SearchGrid.IsWalkableAt(iX - tDx, iY + 1)) || (iParam.SearchGrid.IsWalkableAt(iX, iY - 1) && !iParam.SearchGrid.IsWalkableAt(iX - tDx, iY - 1))) { return(new LPoint(iX, iY)); } } else { if ((iParam.SearchGrid.IsWalkableAt(iX + 1, iY) && !iParam.SearchGrid.IsWalkableAt(iX + 1, iY - tDy)) || (iParam.SearchGrid.IsWalkableAt(iX - 1, iY) && !iParam.SearchGrid.IsWalkableAt(iX - 1, iY - tDy))) { return(new LPoint(iX, iY)); } } } // when moving diagonally, must check for vertical/horizontal jump points if (tDx != 0 && tDy != 0) { jx = jump(iParam, iX + tDx, iY, iX, iY); jy = jump(iParam, iX, iY + tDy, iX, iY); if (jx != null || jy != null) { return(new LPoint(iX, iY)); } } // moving diagonally, must make sure both of the vertical/horizontal // neighbors is open to allow the path if (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY) && iParam.SearchGrid.IsWalkableAt(iX, iY + tDy)) { return(jump(iParam, iX + tDx, iY + tDy, iX, iY)); } else { return(null); } } }
private static LPoint?jumpLoop(JumpPointParam iParam, int iX, int iY, int iPx, int iPy) { LPoint?retVal = null; Stack <JumpSnapshot> stack = new Stack <JumpSnapshot>(); JumpSnapshot currentSnapshot = new JumpSnapshot(); JumpSnapshot newSnapshot = null; currentSnapshot.iX = iX; currentSnapshot.iY = iY; currentSnapshot.iPx = iPx; currentSnapshot.iPy = iPy; currentSnapshot.stage = 0; stack.Push(currentSnapshot); while (stack.Count != 0) { currentSnapshot = stack.Pop(); switch (currentSnapshot.stage) { case 0: if (!iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY)) { retVal = null; continue; } else if (iParam.SearchGrid.GetNodeAt(currentSnapshot.iX, currentSnapshot.iY).Equals(iParam.EndNode)) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } currentSnapshot.tDx = currentSnapshot.iX - currentSnapshot.iPx; currentSnapshot.tDy = currentSnapshot.iY - currentSnapshot.iPy; currentSnapshot.jx = null; currentSnapshot.jy = null; if (iParam.CrossCorner) { // check for forced neighbors // along the diagonal if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0) { if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY)) || (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY - currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY - currentSnapshot.tDy))) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } } // horizontally/vertically else { if (currentSnapshot.tDx != 0) { // moving along x if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + 1)) || (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY - 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY - 1))) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } } else { if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY)) || (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY))) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } } } // when moving diagonally, must check for vertical/horizontal jump points if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0) { currentSnapshot.stage = 1; stack.Push(currentSnapshot); newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } // moving diagonally, must make sure one of the vertical/horizontal // neighbors is open to allow the path // moving diagonally, must make sure one of the vertical/horizontal // neighbors is open to allow the path if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) || iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy)) { newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } else if (iParam.CrossAdjacentPoint) { newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } } else //if (!iParam.CrossCorner) { // check for forced neighbors // along the diagonal if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0) { if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY)) || (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } } // horizontally/vertically else { if (currentSnapshot.tDx != 0) { // moving along x if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY + 1)) || (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY - 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY - 1))) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } } else { if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY - currentSnapshot.tDy)) || (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY - currentSnapshot.tDy))) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } } } // when moving diagonally, must check for vertical/horizontal jump points if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0) { currentSnapshot.stage = 3; stack.Push(currentSnapshot); newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } // moving diagonally, must make sure both of the vertical/horizontal // neighbors is open to allow the path if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy)) { newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } } retVal = null; break; case 1: currentSnapshot.jx = retVal; currentSnapshot.stage = 2; stack.Push(currentSnapshot); newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); break; case 2: currentSnapshot.jy = retVal; if (currentSnapshot.jx != null || currentSnapshot.jy != null) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } // moving diagonally, must make sure one of the vertical/horizontal // neighbors is open to allow the path if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) || iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy)) { newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } else if (iParam.CrossAdjacentPoint) { newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } retVal = null; break; case 3: currentSnapshot.jx = retVal; currentSnapshot.stage = 4; stack.Push(currentSnapshot); newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); break; case 4: currentSnapshot.jy = retVal; if (currentSnapshot.jx != null || currentSnapshot.jy != null) { retVal = new LPoint(currentSnapshot.iX, currentSnapshot.iY); continue; } // moving diagonally, must make sure both of the vertical/horizontal // neighbors is open to allow the path if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy)) { newSnapshot = new JumpSnapshot(); newSnapshot.iX = currentSnapshot.iX + currentSnapshot.tDx; newSnapshot.iY = currentSnapshot.iY + currentSnapshot.tDy; newSnapshot.iPx = currentSnapshot.iX; newSnapshot.iPy = currentSnapshot.iY; newSnapshot.stage = 0; stack.Push(newSnapshot); continue; } retVal = null; break; } } return(retVal); }