/// <summary>
        /// Generates a path on the given map
        /// </summary>
        /// <param name="diagonal"></param>
        /// <returns></returns>
        public List<Point> GeneratePath(bool diagonal = true)
        {
            // Check for whether it's even possible first, and then return early if it's not
            var adjPoint = GetAdjacentCell(_end.Position.X, _end.Position.Y);
            if(adjPoint == new Point(-1, -1))
                return new List<Point>();

            // Otherwise, begin the A* search

            // Start at the beginning
            _openList.Add(_start);
            _current = _start;

            // Let us find where we need to go
            while (true)
            {
                // If we're out of places to go..
                if (_openList.Count == 0)
                    break;

                _current = GetSmallestF();

                if (_current.Position == _end.Position)
                    break;

                _openList.Remove(_current);
                _closedList.Add(_current.Position);

                if (diagonal)
                {
                    AddAdjacentCellToNodeToOpenList(_current, 1, -1, 14);
                    AddAdjacentCellToNodeToOpenList(_current, -1, -1, 14);
                    AddAdjacentCellToNodeToOpenList(_current, -1, 1, 14);
                    AddAdjacentCellToNodeToOpenList(_current, 1, 1, 14);
                }

                AddAdjacentCellToNodeToOpenList(_current, 0, -1, 10);
                AddAdjacentCellToNodeToOpenList(_current, -1, 0, 10);
                AddAdjacentCellToNodeToOpenList(_current, 1, 0, 10);
                AddAdjacentCellToNodeToOpenList(_current, 0, 1, 10);

            }

            while (_current != null)
            {
                bool endOnClosed = false;
                for (int v = 0; v < _openList.Count; v++)
                    if (_openList[v].Position == _end.Position)
                        endOnClosed = true;
                if (endOnClosed)
                    _waypoints.Add(_current.Position);

                // Walk
                _current = _current.Parent;
            }

            _waypoints.Reverse();
            return _waypoints;
        }
        public AStarSearcher(TmxMap map, Point dest, Point start)
        {
            _map = map;

            // Setup our start and goal here
            _start = new GraphNode(start, null);
            _end = new GraphNode(dest, null);
        }
Exemple #3
0
 public GraphNode(Point position, GraphNode parent)
 {
     Position = position;
     Parent = parent;
 }
        private void AddAdjacentCellToNodeToOpenList(GraphNode parentNode, int xOffset, int yOffset, int gCost)
        {
            // Get adjacent cell
            var adjacentCell = GetAdjacentCell(parentNode.Position.X + xOffset, parentNode.Position.Y + yOffset);

            // Ignore blocked and invalid points
            if (adjacentCell == new Point(-1, -1))
                return;

            /**
             *
             *      1) A* requires searching the entire god damn map sometimes; runs on the same thread; will search every node to find a path just to find out that it's not traversable

                    2) If the path-finding leads to somewhere that is ultimately not reachable, the code will stutter horribly and die.

                    Optimizations:

                    1) Make sure we don't bother path finding to a place that is unreachable
                    2) Remove linearity from closedList; replace it with something more high speed (O(1), hash set?)
             *
             *      #2 was implemented here, gains are huge as is vs. a linear search
             *
             *
             */

            // Ignore stuff on the closed list; hash set for performance reasons
            if (_closedList.Contains(adjacentCell))
                return;

            var adjacentNode = _openList.SingleOrDefault(n => n.Position == adjacentCell);

            if (adjacentNode != null)
            {
                if (parentNode.G + gCost < adjacentNode.G)
                {
                    adjacentNode.Parent = parentNode;
                    adjacentNode.G = parentNode.G + gCost;
                    adjacentNode.F = adjacentNode.G + adjacentNode.H;
                }

                return;
            }

            // Otherwise, set some parameters for ourselves
            var dist = GetDistance(adjacentCell, _end.Position);
            var newNode = new GraphNode(adjacentCell, parentNode) { G = gCost, H = dist };
            newNode.F = newNode.G + newNode.H;
            _openList.Add(newNode);
        }