/// <summary> /// Constructor. /// </summary> public Pathfinder(Map map) { levelWidth = map.Width; levelHeight = map.Height; InitializeSearchNodes(map); }
/// <summary> /// Constructor. /// </summary> /// <param name="map">Current level's map.</param> public Pathfinder(Map map) { this.levelWidth = map.Width; this.levelHeight = map.Height; this.InitializeSearchNodes(map); // FOR TEST this.Target = new Point(map.Width - 1, map.Height - 1); }
/// <summary> /// Splits the level up into a grid of nodes. /// </summary> private void InitializeSearchNodes(Map map) { searchNodes = new SearchNode[levelWidth, levelHeight]; // Create node for each tile. CreateNodeForEachTile(map); // Connect each node with its neighbours. ConnectEachNodeWithNeighbours(); }
/// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// </summary> protected override void Initialize() { // Initialize window GraphicsInitialization(); this.map = new Map(this); pathfinder = new Pathfinder(map); Stack<Vector2> path = pathfinder.FindPath(new Point(0, 0), map, new Point(12, 26)); foreach (Vector2 point in path) { System.Diagnostics.Debug.WriteLine(point); } zombie = new DrawableObject(this, Vector2.Zero); zombie.Path = path; base.Initialize(); }
// <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; } } } }
/// <summary> /// Ininitializes the srating node and add it to the open list. /// </summary> private void InitializeStartnode(Point currentPosition, Map map, List<SearchNode> openList) { searchNodes[currentPosition.X, currentPosition.Y].G = 0; searchNodes[currentPosition.X, currentPosition.Y].CalculateHValue(map, Target); openList.Add(searchNodes[currentPosition.X, currentPosition.Y]); searchNodes[currentPosition.X, currentPosition.Y].InOpenList = true; }
/// <summary> /// Do the pathfinding from current point /// </summary> public Stack<Vector2> FindPath(Point startPoint, Map map, Point endPoint) { var startNode = searchNodes[startPoint.X, startPoint.Y]; var endNode = searchNodes[endPoint.X, endPoint.Y]; // Check if current position is outside the map if ((startPoint.X > map.Width - 1 || startPoint.X < 0) || (startPoint.Y < 0 || startPoint.Y > map.Height - 1)) { throw new ApplicationException("Starting point for search is outside the boundaries of the map!"); } var openList = new List<SearchNode>(); var closeList = new List<SearchNode>(); InitializeStartnode(startPoint, map, openList); while (openList.Count > 0) { // Finds next active node (minimal F value) SearchNode activeNode = FindBestNode(openList); ProcessNeighbours(activeNode, openList); // Drop current active node from drop list openList.Remove(activeNode); // TO BE cONSIDERED IT'S SLOW!!! activeNode.InOpenList = false; closeList.Add(activeNode); activeNode.InClosedList = true; // Check if target is found. if (searchNodes[endPoint.X, endPoint.Y].InClosedList) { break; // TODO Return path. } } // Save the path var path = FindFinalPath(startNode, endNode, closeList); return path; }
/// <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; } } } }
/// <summary> /// Calculates the H value. /// </summary> public void CalculateHValue(Map map, Point target) { this.H = 10 * (Math.Abs(this.Position.X - target.X) + Math.Abs(this.Position.Y - target.Y)); }