예제 #1
0
        /// <summary>
        /// Traverse neghbours and store a reference to it if possible.
        /// </summary>
        private void AddReferencesToNeighbours(Point[] neighbourPositions, SearchNode node)
        {
            for (int count = 0; count < neighbourPositions.Length; count++)
            {
                Point position = neighbourPositions[count];

                // Check if the neighbour is part of the level.
                if ((position.X >= 0 && position.X <= levelWidth - 1) &&
                    (position.Y >= 0 && position.Y <= levelHeight - 1))
                {
                    SearchNode neighbour = searchNodes[position.X, position.Y];

                    // Add only walkable nodes.
                    if (neighbour != null && neighbour.Walkable)
                    {
                        // Store a reference to the neighbour.
                        node.Neighbours.Add(neighbour);
                    }
                }
            }
        }
예제 #2
0
        // <summary>
        /// Splits our level up into a grid of nodes.
        /// </summary>
        private void InitializeSearchNodes(Map map)
        {
            searchNodes = new SearchNode[levelWidth, levelHeight];

            //For each of the tiles in our map, we
            // will create a search node for it.
            for (int x = 0; x < levelWidth; x++)
            {
                for (int y = 0; y < levelHeight; y++)
                {
                    //Create a search node to represent this tile.
                    SearchNode node = new SearchNode();
                    node.Position = new Point(x, y);

                    // Our enemies can only walk on grass tiles.
                    node.Walkable = map.GetIndex(x, y) == 0;

                    // We only want to store nodes
                    // that can be walked on.
                    if (node.Walkable == true)
                    {
                        node.Neighbors = new SearchNode[4];
                        searchNodes[x, y] = node;
                    }
                }
            }

            // Now for each of the search nodes, we will
            // connect it to each of its neighbours.
            for (int x = 0; x < levelWidth; x++)
            {
                for (int y = 0; y < levelHeight; y++)
                {
                    SearchNode node = searchNodes[x, y];

                    // We only want to look at the nodes that 
                    // our enemies can walk on.
                    if (node == null || node.Walkable == false)
                    {
                        continue;
                    }

                    // An array of all of the possible neighbors this 
                    // node could have. (We will ignore diagonals for now.)
                    Point[] neighbors = new Point[]
                    {
                        new Point (x, y - 1), // The node above the current node
                        new Point (x, y + 1), // The node below the current node.
                        new Point (x - 1, y), // The node left of the current node.
                        new Point (x + 1, y), // The node right of the current node
                    };

                    // We loop through each of the possible neighbors
                    for (int i = 0; i < neighbors.Length; i++)
                    {
                        Point position = neighbors[i];

                        // We need to make sure this neighbour is part of the level.
                        if (position.X < 0 || position.X > levelWidth - 1 ||
                            position.Y < 0 || position.Y > levelHeight - 1)
                        {
                            continue;
                        }

                        SearchNode neighbor = searchNodes[position.X, position.Y];

                        // We will only bother keeping a reference 
                        // to the nodes that can be walked on.
                        if (neighbor == null || neighbor.Walkable == false)
                        {
                            continue;
                        }

                        // Store a reference to the neighbor.
                        node.Neighbors[i] = neighbor;
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Use the parent field of the search nodes to trace
        /// a path from the end node to the start node.
        /// </summary>
        private List<Vector2> FindFinalPath(SearchNode startNode, SearchNode endNode)
        {
            closedList.Add(endNode);

            SearchNode parentTile = endNode.Parent;

            // Trace back through the nodes using the parent fields
            // to find the best path.
            while (parentTile != startNode)
            {
                closedList.Add(parentTile);
                parentTile = parentTile.Parent;
            }

            List<Vector2> finalPath = new List<Vector2>();

            // Reverse the path and transform into world space.
            for (int i = closedList.Count - 1; i >= 0; i--)
            {
                finalPath.Add(new Vector2(closedList[i].Position.X * 32,
                                          closedList[i].Position.Y * 32));
            }

            return finalPath;
        }
예제 #4
0
        private void ProcessNeighbours(SearchNode activeNode, List<SearchNode> openList)
        {
            foreach (var node in activeNode.Neighbours)
            {
                if (node.Walkable && !node.InClosedList)
                {
                    if (!node.InOpenList)
                    {
                        // Add neighbours to open list if it isn't already there
                        openList.Add(node);
                        node.InOpenList = true;

                        // Mark active node as parent.
                        node.SetParent(activeNode);

                        // Set G value.
                        node.G = activeNode.G + 10;
                    }
                    else
                    {
                        int tempG = activeNode.G + 10; // 10 IF THERE IS NO DIAGONAL
                        if (node.G < 0 || node.G > tempG)
                        {
                            tempG = node.G;

                            // Mark active node as parent.
                            node.SetParent(activeNode);
                        }
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Use the parent field of the search nodes to trace
        /// a path from the end node to the start node.
        /// </summary>
        private Stack<Vector2> FindFinalPath(SearchNode startNode, SearchNode endNode, List<SearchNode> closeList)
        {
            closeList.Add(endNode);
            SearchNode parentTile = endNode.Parent;
            var finalPath = new Stack<Vector2>();

            // Trace back through the nodes using the parent fields
            while (parentTile != startNode)
            {
                finalPath.Push(new Vector2(parentTile.Position.X * (int)Global.TileSize, parentTile.Position.Y * (int)Global.TileSize));
                parentTile = parentTile.Parent;
            }


            // Reverse the path and transform into world space.
            finalPath.Reverse();

            return finalPath;
        }
예제 #6
0
        private SearchNode FindBestNode(List<SearchNode> openList)
        {
            SearchNode activeNode = new SearchNode();

            // Finds next active node (minimal F value)
            int minF = int.MaxValue;
            foreach (var node in openList)
            {
                if (node.F < minF)
                {
                    minF = node.F;
                    activeNode = node;
                }
            }
            return activeNode;
        }
예제 #7
0
        /// <summary>
        /// Creates node for each tile.
        /// </summary>
        private void CreateNodeForEachTile(Map map)
        {
            for (int coordX = 0; coordX < levelWidth; coordX++)
            {
                for (int coordY = 0; coordY < levelHeight; coordY++)
                {
                    var node = new SearchNode();
                    node.Position = new Point(coordX, coordY);

                    // Mark walkable terrain. 0 represent path on map grid.
                    node.Walkable = map.GetValue(coordX, coordY) == WalkableLandValue;

                    // Store only walkable nodes.
                    if (node.Walkable)
                    {
                        node.Neighbours = new List<SearchNode>(); // TO BE CONSIDERED!!!
                        searchNodes[coordX, coordY] = node;
                    }
                }
            }
        }
예제 #8
0
 /// <summary>
 /// Sets provided node as parent.
 /// </summary>
 public void SetParent(SearchNode parent)
 {
     this.Parent = parent;
     this.F = this.G + this.H;
 }
예제 #9
0
        // <summary>
        /// Splits our level up into a grid of nodes.
        /// </summary>
        private void InitializeSearchNodes(Map map)
        {
            searchNodes = new SearchNode[levelWidth, levelHeight];

            //For each of the tiles in our map, we
            // will create a search node for it.
            for (int x = 0; x < levelWidth; x++)
            {
                for (int y = 0; y < levelHeight; y++)
                {
                    //Create a search node to represent this tile.
                    SearchNode node = new SearchNode();
                    node.Position = new Point(x, y);

                    // Our enemies can only walk on grass tiles.
                    node.Walkable = map.GetIndex(x, y) == 0;

                    // We only want to store nodes
                    // that can be walked on.
                    if (node.Walkable == true)
                    {
                        node.Neighbors    = new SearchNode[4];
                        searchNodes[x, y] = node;
                    }
                }
            }

            // Now for each of the search nodes, we will
            // connect it to each of its neighbours.
            for (int x = 0; x < levelWidth; x++)
            {
                for (int y = 0; y < levelHeight; y++)
                {
                    SearchNode node = searchNodes[x, y];

                    // We only want to look at the nodes that
                    // our enemies can walk on.
                    if (node == null || node.Walkable == false)
                    {
                        continue;
                    }

                    // An array of all of the possible neighbors this
                    // node could have. (We will ignore diagonals for now.)
                    Point[] neighbors = new Point[]
                    {
                        new Point(x, y - 1),  // The node above the current node
                        new Point(x, y + 1),  // The node below the current node.
                        new Point(x - 1, y),  // The node left of the current node.
                        new Point(x + 1, y),  // The node right of the current node
                    };

                    // We loop through each of the possible neighbors
                    for (int i = 0; i < neighbors.Length; i++)
                    {
                        Point position = neighbors[i];

                        // We need to make sure this neighbour is part of the level.
                        if (position.X < 0 || position.X > levelWidth - 1 ||
                            position.Y < 0 || position.Y > levelHeight - 1)
                        {
                            continue;
                        }

                        SearchNode neighbor = searchNodes[position.X, position.Y];

                        // We will only bother keeping a reference
                        // to the nodes that can be walked on.
                        if (neighbor == null || neighbor.Walkable == false)
                        {
                            continue;
                        }

                        // Store a reference to the neighbor.
                        node.Neighbors[i] = neighbor;
                    }
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Finds the optimal path from one point to another.
        /// </summary>
        public List <Vector2> FindPath(Point startPoint, Point endPoint)
        {
            // Only try to find a path if the start and end points are different.
            if (startPoint == endPoint)
            {
                return(new List <Vector2>());
            }

            /////////////////////////////////////////////////////////////////////
            // Step 1 : Clear the Open and Closed Lists and reset each node’s F
            //          and G values in case they are still set from the last
            //          time we tried to find a path.
            /////////////////////////////////////////////////////////////////////
            ResetSearchNodes();

            // Store references to the start and end nodes for convenience.
            SearchNode startNode = searchNodes[startPoint.X, startPoint.Y];
            SearchNode endNode   = searchNodes[endPoint.X, endPoint.Y];

            /////////////////////////////////////////////////////////////////////
            // Step 2 : Set the start node’s G value to 0 and its F value to the
            //          estimated distance between the start node and goal node
            //          (this is where our H function comes in) and add it to the
            //          Open List.
            /////////////////////////////////////////////////////////////////////
            startNode.InOpenList = true;

            startNode.DistanceToGoal   = Heuristic(startPoint, endPoint);
            startNode.DistanceTraveled = 0;

            openList.Add(startNode);

            /////////////////////////////////////////////////////////////////////
            // Setp 3 : While there are still nodes to look at in the Open list :
            /////////////////////////////////////////////////////////////////////
            while (openList.Count > 0)
            {
                /////////////////////////////////////////////////////////////////
                // a) : Loop through the Open List and find the node that
                //      has the smallest F value.
                /////////////////////////////////////////////////////////////////
                SearchNode currentNode = FindBestNode();

                /////////////////////////////////////////////////////////////////
                // b) : If the Open List empty or no node can be found,
                //      no path can be found so the algorithm terminates.
                /////////////////////////////////////////////////////////////////
                if (currentNode == null)
                {
                    break;
                }

                /////////////////////////////////////////////////////////////////
                // c) : If the Active Node is the goal node, we will
                //      find and return the final path.
                /////////////////////////////////////////////////////////////////
                if (currentNode == endNode)
                {
                    // Trace our path back to the start.
                    return(FindFinalPath(startNode, endNode));
                }

                /////////////////////////////////////////////////////////////////
                // d) : Else, for each of the Active Node’s neighbours :
                /////////////////////////////////////////////////////////////////
                for (int i = 0; i < currentNode.Neighbors.Length; i++)
                {
                    SearchNode neighbor = currentNode.Neighbors[i];

                    //////////////////////////////////////////////////
                    // i) : Make sure that the neighbouring node can
                    //      be walked across.
                    //////////////////////////////////////////////////
                    if (neighbor == null || neighbor.Walkable == false)
                    {
                        continue;
                    }

                    //////////////////////////////////////////////////
                    // ii) Calculate a new G value for the neighbouring node.
                    //////////////////////////////////////////////////
                    float distanceTraveled = currentNode.DistanceTraveled + 1;

                    // An estimate of the distance from this node to the end node.
                    float heuristic = Heuristic(neighbor.Position, endPoint);

                    //////////////////////////////////////////////////
                    // iii) If the neighbouring node is not in either the Open
                    //      List or the Closed List :
                    //////////////////////////////////////////////////
                    if (neighbor.InOpenList == false && neighbor.InClosedList == false)
                    {
                        // (1) Set the neighbouring node’s G value to the G value we just calculated.
                        neighbor.DistanceTraveled = distanceTraveled;
                        // (2) Set the neighbouring node’s F value to the new G value + the estimated
                        //     distance between the neighbouring node and goal node.
                        neighbor.DistanceToGoal = distanceTraveled + heuristic;
                        // (3) Set the neighbouring node’s Parent property to point at the Active Node.
                        neighbor.Parent = currentNode;
                        // (4) Add the neighbouring node to the Open List.
                        neighbor.InOpenList = true;
                        openList.Add(neighbor);
                    }
                    //////////////////////////////////////////////////
                    // iv) Else if the neighbouring node is in either the Open
                    //     List or the Closed List :
                    //////////////////////////////////////////////////
                    else if (neighbor.InOpenList || neighbor.InClosedList)
                    {
                        // (1) If our new G value is less than the neighbouring
                        //     node’s G value, we basically do exactly the same
                        //     steps as if the nodes are not in the Open and
                        //     Closed Lists except we do not need to add this node
                        //     the Open List again.
                        if (neighbor.DistanceTraveled > distanceTraveled)
                        {
                            neighbor.DistanceTraveled = distanceTraveled;
                            neighbor.DistanceToGoal   = distanceTraveled + heuristic;

                            neighbor.Parent = currentNode;
                        }
                    }
                }

                /////////////////////////////////////////////////////////////////
                // e) Remove the Active Node from the Open List and add it to the
                //    Closed List
                /////////////////////////////////////////////////////////////////
                openList.Remove(currentNode);
                currentNode.InClosedList = true;
            }

            // No path could be found.
            return(new List <Vector2>());
        }