public GridDirection GetBestDirection(GridPosition position) { GridPosition offset = position - this; if (Mathf.Abs(offset.column) > Mathf.Abs(offset.row)) { if (offset.column > 0) { return GridDirection.East; } else { return GridDirection.West; } } else { if (offset.row > 0) { return GridDirection.North; } else { return GridDirection.South; } } }
public bool Contains(GridPosition pos) { return pos.column >= min.column && pos.column <= max.column && pos.row >= min.row && pos.row <= max.row; }
public GridRectangle(GridPosition posOne, GridPosition posTwo) { int minCol = Mathf.Min(posOne.column, posTwo.column); int minRow = Mathf.Min(posOne.row, posTwo.row); int maxCol = Mathf.Max(posOne.column, posTwo.column); int maxRow = Mathf.Max(posOne.row, posTwo.row); min = new GridPosition(minCol, minRow); max = new GridPosition(maxCol, maxRow); }
public void AddPosition(int column, int row) { if (count == _path.Count - 1) { _path.Add(new GridPosition(column, row)); count++; return; } //// for class //GridPosition pos = _path[count]; //pos.row = row; //pos.column = column; // for struct _path[count] = new GridPosition(column, row); count++; }
// calculate direction from this position to other position public GridDirection GetDirection(GridPosition position) { // top if (position.row < this.row) { return GridDirection.North; } // right if (position.column > this.column) { return GridDirection.East; } // bottom if (position.row > this.row) { return GridDirection.South; } // left return GridDirection.West; }
// calculates path from startPos to endPos public bool FindPath(GridPosition startPos, GridPosition endPos, MovementPossibleCheck movementPossible = null, bool saveNearestPath = true, int maxNodeChecksWithoutProgress = 0) { // assume no path found gridPath.Clear(); if (startPos.row < 0 || startPos.column < 0 || endPos.row < 0 || endPos.column < 0 || startPos.column >= _columnCount || startPos.row >= _rowCount || endPos.column >= _columnCount || endPos.row >= _rowCount) { return false; } // reset open and closed list _openList.Clear(); for (int field = 0; field < _fieldCount; field++) { GridPathNode node = _grid[field]; if (node.closed) node.closed = false; } // set target values int targetNodeIndex = endPos.row * _columnCount + endPos.column; GridPathNode targetNode = _grid[targetNodeIndex]; // check if end point is walkable and then decide if using brute force or sophisticated // brute force works better when no path will be found and maxNodeChecksWithoutProgress is not set bool bruteForce = false; bool movementFromStartToEndIsPossible = false; if (movementPossible != null) movementFromStartToEndIsPossible = movementPossible(startPos.column, startPos.row, endPos.column, endPos.row); else movementFromStartToEndIsPossible = targetNode.walkable; // check if sophisticated or brute force approach if (!movementFromStartToEndIsPossible && maxNodeChecksWithoutProgress <= 0) { // brute force _heuristicValue = 1; bruteForce = true; } else { // sophisticated _heuristicValue = 10; } // set nearest point _nearestDistance = int.MaxValue; _lastTimeNearestPointPushedForward = 0; // add the starting point to the open list int startNodeIndex = startPos.row * _columnCount + startPos.column; GridPathNode startNode = _grid[startNodeIndex]; _openList.Add(startNode); startNode.h = GetHeuristic(startPos.row, startPos.column, endPos.row, endPos.column); startNode.opened = true; _nearestPoint = startNode; // starting point is also nearest point at the moment // while not found and still nodes to check while (targetNode.closed == false && _openList.Count > 0 // and while not the maximum of checks without real progress && (maxNodeChecksWithoutProgress <= 0 || _lastTimeNearestPointPushedForward < maxNodeChecksWithoutProgress)) { // first node in the openList will become the current node GridPathNode currentNode = _openList[0]; // save nearest field if (currentNode.h < _nearestDistance) { _nearestDistance = currentNode.h; _nearestPoint = currentNode; _lastTimeNearestPointPushedForward = 0; } else { _lastTimeNearestPointPushedForward++; } // mark current node as closed currentNode.closed = true; currentNode.opened = false; _openList.RemoveAt(0); for (int i = 0; i < currentNode.directionCount; i++) { GridPathNode.GridMovement gridMovement = currentNode.directions[i]; GridPathNode checkNode = gridMovement.node; // if node is already closed, ignore it if (checkNode.closed) continue; // movement not possible => ignore if (movementPossible == null) { if (checkNode.walkable == false) continue; } else { if (movementPossible(currentNode.column, currentNode.row, checkNode.column, checkNode.row) == false) continue; } // possible movement cost including path to currentNode int g = currentNode.g + gridMovement.movementCost; if (checkNode.opened == false) { checkNode.parentIndex = currentNode.index; checkNode.h = GetHeuristic(checkNode.row, checkNode.column, endPos.row, endPos.column); checkNode.g = g; checkNode.f = checkNode.g + checkNode.h; checkNode.opened = true; if (bruteForce) _openList.Add(checkNode); else AddToOpenList(checkNode); } else { // checkNode is on open list // if path to this checkNode is better from the current Node, update if (checkNode.g > g) { // update parent to the current Node checkNode.parentIndex = currentNode.index; // update path cost, checkNode.h already calculated checkNode.g = g; checkNode.f = checkNode.g + checkNode.h; // do not bother to move node to correct spot in open list, // this way it's faster } } } } // clear opened values for next search int openListCount = _openList.Count; for (int i = 0; i < openListCount; i++) { GridPathNode node = _openList[i]; node.opened = false; } // if target found if (targetNode.closed) { CreatePath(startNodeIndex, targetNodeIndex); return true; } // save nearest path if wished else if (saveNearestPath) { CreatePath(startNodeIndex, _nearestPoint.row * _columnCount + _nearestPoint.column); return false; } // no path and no nearest point else { return false; } }
// ====================================================================== // public methods // ---------------------------------------------------------------------- // calculate Manhattan Distance to other position public int GetDistance(GridPosition position) { return UnityEngine.Mathf.Abs(this.column - position.column) + UnityEngine.Mathf.Abs(this.row - position.row); }
public bool IsAdjacent(GridPosition checkPoint) { int distanceX = UnityEngine.Mathf.Abs(this.column - checkPoint.column); int distanceY = UnityEngine.Mathf.Abs(this.row - checkPoint.row); return distanceX + distanceY == 1; }
public bool IsAdjacentOrDiagonal(GridPosition checkPoint) { int distanceX = UnityEngine.Mathf.Abs(this.column - checkPoint.column); int distanceY = UnityEngine.Mathf.Abs(this.row - checkPoint.row); if (distanceX <= 1 && distanceY <= 1) return true; else return false; }
// get position next to this one public GridPosition GetAdjacentPosition(GridDirection direction) { GridPosition position = new GridPosition(column, row); // top if (direction == GridDirection.North) { position.row++; } // right if (direction == GridDirection.East) { position.column++; } // bottom if (direction == GridDirection.South) { position.row--; } // left if (direction == GridDirection.West) { position.column--; } return position; }
// calculates path from startPos to endPos public bool FindPath(GridPosition startPos, GridPosition endPos, MovementPossibleCheck movementPossible = null, bool saveNearestPath = true, int maxNodeChecksWithoutProgress = 0) { // assume no path found gridPath.Clear(); if (startPos.row < 0 || startPos.column < 0 || endPos.row < 0 || endPos.column < 0 || startPos.column >= _columnCount || startPos.row >= _rowCount || endPos.column >= _columnCount || endPos.row >= _rowCount) { return(false); } // reset open and closed list _openList.Clear(); for (int field = 0; field < _fieldCount; field++) { GridPathNode node = _grid[field]; if (node.closed) { node.closed = false; } } // set target values int targetNodeIndex = endPos.row * _columnCount + endPos.column; GridPathNode targetNode = _grid[targetNodeIndex]; // check if end point is walkable and then decide if using brute force or sophisticated // brute force works better when no path will be found and maxNodeChecksWithoutProgress is not set bool bruteForce = false; bool movementFromStartToEndIsPossible = false; if (movementPossible != null) { movementFromStartToEndIsPossible = movementPossible(startPos.column, startPos.row, endPos.column, endPos.row); } else { movementFromStartToEndIsPossible = targetNode.walkable; } // check if sophisticated or brute force approach if (!movementFromStartToEndIsPossible && maxNodeChecksWithoutProgress <= 0) { // brute force _heuristicValue = 1; bruteForce = true; } else { // sophisticated _heuristicValue = 10; } // set nearest point _nearestDistance = int.MaxValue; _lastTimeNearestPointPushedForward = 0; // add the starting point to the open list int startNodeIndex = startPos.row * _columnCount + startPos.column; GridPathNode startNode = _grid[startNodeIndex]; _openList.Add(startNode); startNode.h = GetHeuristic(startPos.row, startPos.column, endPos.row, endPos.column); startNode.opened = true; _nearestPoint = startNode; // starting point is also nearest point at the moment // while not found and still nodes to check while (targetNode.closed == false && _openList.Count > 0 // and while not the maximum of checks without real progress && (maxNodeChecksWithoutProgress <= 0 || _lastTimeNearestPointPushedForward < maxNodeChecksWithoutProgress)) { // first node in the openList will become the current node GridPathNode currentNode = _openList[0]; // save nearest field if (currentNode.h < _nearestDistance) { _nearestDistance = currentNode.h; _nearestPoint = currentNode; _lastTimeNearestPointPushedForward = 0; } else { _lastTimeNearestPointPushedForward++; } // mark current node as closed currentNode.closed = true; currentNode.opened = false; _openList.RemoveAt(0); for (int i = 0; i < currentNode.directionCount; i++) { GridPathNode.GridMovement gridMovement = currentNode.directions[i]; GridPathNode checkNode = gridMovement.node; // if node is already closed, ignore it if (checkNode.closed) { continue; } // movement not possible => ignore if (movementPossible == null) { if (checkNode.walkable == false) { continue; } } else { if (movementPossible(currentNode.column, currentNode.row, checkNode.column, checkNode.row) == false) { continue; } } // possible movement cost including path to currentNode int g = currentNode.g + gridMovement.movementCost; if (checkNode.opened == false) { checkNode.parentIndex = currentNode.index; checkNode.h = GetHeuristic(checkNode.row, checkNode.column, endPos.row, endPos.column); checkNode.g = g; checkNode.f = checkNode.g + checkNode.h; checkNode.opened = true; if (bruteForce) { _openList.Add(checkNode); } else { AddToOpenList(checkNode); } } else { // checkNode is on open list // if path to this checkNode is better from the current Node, update if (checkNode.g > g) { // update parent to the current Node checkNode.parentIndex = currentNode.index; // update path cost, checkNode.h already calculated checkNode.g = g; checkNode.f = checkNode.g + checkNode.h; // do not bother to move node to correct spot in open list, // this way it's faster } } } } // clear opened values for next search int openListCount = _openList.Count; for (int i = 0; i < openListCount; i++) { GridPathNode node = _openList[i]; node.opened = false; } // if target found if (targetNode.closed) { CreatePath(startNodeIndex, targetNodeIndex); return(true); } // save nearest path if wished else if (saveNearestPath) { CreatePath(startNodeIndex, _nearestPoint.row * _columnCount + _nearestPoint.column); return(false); } // no path and no nearest point else { return(false); } }
protected Vector2 GetLevelPositionFromGridPosition(GridPosition pos) { return(new Vector2(GetPositionFromColumn(pos.column), GetPositionFromRow(pos.row))); }
protected Vector2 GetLevelPositionFromGridPosition(GridPosition pos) { return new Vector2(GetPositionFromColumn(pos.column), GetPositionFromRow(pos.row)); }