private float Heuristic_cost_estimate(Path_Node <Tile> a, Path_Node <Tile> b) { if (b == null) { return(0f); } return((float)Math.Sqrt(Math.Pow(a.data.position.X - b.data.position.X, 2) + Math.Pow(a.data.position.Y - b.data.position.Y, 2))); }
public Path_TileGraph(World world) { nodes = new Dictionary <Tile, Path_Node <Tile> >(); for (int x = 0; x < world.size.X; x++) { for (int y = 0; y < world.size.Y; y++) { Tile t = world.GetTileAt(x, y); if (t.movementCost > 0) { Path_Node <Tile> n = new Path_Node <Tile>(); n.data = t; nodes.Add(t, n); } } } // Debug.WriteLine("Path_TileGraph: Created " + nodes.Count + " nodes."); int edgeCount = 0; foreach (Tile t in nodes.Keys) { Path_Node <Tile> n = nodes[t]; List <Path_Edge <Tile> > edges = new List <Path_Edge <Tile> >(); Tile[] neighbours = t.GetNeighbours(); for (int i = 0; i < neighbours.Length; i++) { if (neighbours[i] != null && neighbours[i].movementCost > 0 && IsClippingCorner(t, neighbours[i]) == false) { Path_Edge <Tile> e = new Path_Edge <Tile>(); e.cost = neighbours[i].movementCost; e.node = nodes[neighbours[i]]; edges.Add(e); edgeCount++; } } n.edges = edges.ToArray(); } //Debug.WriteLine("Path_TileGraph: Created " + edgeCount + " edges."); }
private void GenerateEdgesByTile(Tile t) { Path_Node <Tile> n = nodes[t]; List <Path_Edge <Tile> > edges = new List <Path_Edge <Tile> >(); Tile[] neighbours = t.GetNeighbours(); for (int i = 0; i < neighbours.Length; i++) { if (neighbours[i] != null && neighbours[i].movementCost > 0 && IsClippingCorner(t, neighbours[i]) == false) { Path_Edge <Tile> e = new Path_Edge <Tile>(); e.cost = neighbours[i].movementCost; e.node = nodes[neighbours[i]]; edges.Add(e); } } n.edges = edges.ToArray(); }
private float Dist_between(Path_Node <Tile> a, Path_Node <Tile> b) { // We can make assumptions because we know we're working // on a grid at this point. // Hori/Vert neighbours have a distance of 1 if (Math.Abs(a.data.position.X - b.data.position.X) + Math.Abs(a.data.position.Y - b.data.position.Y) == 1) { return(1f); } // Diag neighbours have a distance of 1.41421356237 if (Math.Abs(a.data.position.X - b.data.position.X) == 1 && Math.Abs(a.data.position.Y - b.data.position.Y) == 1) { return(1.4f); } // Otherwise, do the actual math. return((float)Math.Sqrt( Math.Pow(a.data.position.X - b.data.position.X, 2) + Math.Pow(a.data.position.Y - b.data.position.Y, 2))); }
public Path_AStar(World world, Tile tileStart, Tile tileEnd) { if (world.tileGraph == null) { world.tileGraph = new Path_TileGraph(world); } Dictionary <Tile, Path_Node <Tile> > nodes = world.tileGraph.nodes; if (nodes.ContainsKey(tileStart) == false) { Debug.WriteLine("Path_AStar: The starting tile isn't in the list of nodes!"); return; } Path_Node <Tile> start = nodes[tileStart]; Path_Node <Tile> goal = null; if (tileEnd != null) { if (nodes.ContainsKey(tileEnd) == false) { Debug.WriteLine("Path_AStar: The ending tile isn't in the list of nodes!"); return; } goal = nodes[tileEnd]; } HashSet <Path_Node <Tile> > closedSet = new HashSet <Path_Node <Tile> >(); SimplePriorityQueue <Path_Node <Tile> > openSet = new SimplePriorityQueue <Path_Node <Tile> >(); openSet.Enqueue(start, 0); Dictionary <Path_Node <Tile>, Path_Node <Tile> > cameFrom = new Dictionary <Path_Node <Tile>, Path_Node <Tile> >(); Dictionary <Path_Node <Tile>, float> gScore = new Dictionary <Path_Node <Tile>, float>(); gScore[start] = 0; Dictionary <Path_Node <Tile>, float> fScore = new Dictionary <Path_Node <Tile>, float>(); fScore[start] = Heuristic_cost_estimate(start, goal); while (openSet.Count > 0) { Path_Node <Tile> current = openSet.Dequeue(); // Debug.WriteLine("Next Node: X:" + current.data.position.X + " Y:" + current.data.position.Y); if (goal != null) { if (current == goal) { reconstructPath(cameFrom, current); return; } } closedSet.Add(current); foreach (Path_Edge <Tile> edgeNeighbour in current.edges) { Path_Node <Tile> neighbour = edgeNeighbour.node; if (closedSet.Contains(neighbour)) { continue; } float movementCostToNeighbour = neighbour.data.movementCost * Dist_between(current, neighbour); float tentativeGScore = gScore[current] + movementCostToNeighbour; if (openSet.Contains(neighbour) && tentativeGScore >= gScore[neighbour]) { continue; } cameFrom[neighbour] = current; gScore[neighbour] = tentativeGScore; fScore[neighbour] = gScore[neighbour] + Heuristic_cost_estimate(neighbour, goal); if (openSet.Contains(neighbour) == false) { openSet.Enqueue(neighbour, fScore[neighbour]); } else { openSet.UpdatePriority(neighbour, fScore[neighbour]); } } } }
private void reconstructPath(Dictionary <Path_Node <Tile>, Path_Node <Tile> > cameFrom, Path_Node <Tile> current) { Queue <Tile> totalPath = new Queue <Tile>(); totalPath.Enqueue(current.data); while (cameFrom.ContainsKey(current)) { current = cameFrom[current]; totalPath.Enqueue(current.data); //Debug.WriteLine("Moving to new tile, X: " + current.data.position.X + " Y: " + current.data.position.Y); } path = new Queue <Tile>(totalPath.Reverse()); //Debug.WriteLine("Path size: " + path.Count); }