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;
		}
示例#11
0
        // 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);
            }
        }
示例#12
0
 protected Vector2 GetLevelPositionFromGridPosition(GridPosition pos)
 {
     return(new Vector2(GetPositionFromColumn(pos.column), GetPositionFromRow(pos.row)));
 }
示例#13
0
		protected Vector2 GetLevelPositionFromGridPosition(GridPosition pos)
        {
            return new Vector2(GetPositionFromColumn(pos.column), GetPositionFromRow(pos.row));
        }