Advertisement
svetliaka92

Pathfinding.cs

Feb 27th, 2020
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.84 KB | None | 0 0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5.  
  6. public class Pathfinding
  7. {
  8.     private const int MOVE_STRAIGHT_COST = 5;
  9.     private const int MOVE_DIAGONAL_COST = 7;
  10.  
  11.     private static Pathfinding _instance;
  12.     public static Pathfinding Instance => _instance;
  13.  
  14.     private Grid grid;
  15.  
  16.     private List<Tile> openList;
  17.     private List<Tile> closedList;
  18.  
  19.     public Pathfinding(Grid grid)
  20.     {
  21.         _instance = this;
  22.         this.grid = grid;
  23.     }
  24.  
  25.     public List<Tile> FindPath(int startX, int startY, int endX, int endY, int movementPoints)
  26.     {
  27.         Tile startTile = grid.GetGridObject(startX, startY);
  28.         Tile endTile = grid.GetGridObject(endX, endY);
  29.  
  30.         openList = new List<Tile> { startTile };
  31.         closedList = new List<Tile>();
  32.  
  33.         for (int x = 0; x < grid.GridSizeX; x++)
  34.         {
  35.             for (int y = 0; y < grid.GridSizeY; y++)
  36.             {
  37.                 Tile tile = grid.GetGridObject(x, y);
  38.                 tile.gCost = int.MaxValue;
  39.                 tile.cameFromTile = null;
  40.             }
  41.         }
  42.  
  43.         startTile.gCost = 0;
  44.         startTile.hCost = CalculateDistanceCost(startTile, endTile);
  45.  
  46.         while (openList.Count > 0)
  47.         {
  48.             Tile currentTile = GetLowestFCostNode(openList);
  49.             if (currentTile == endTile)
  50.             {
  51.                 // reached end
  52.                 return CalculatePath(endTile);
  53.             }
  54.  
  55.             openList.Remove(currentTile);
  56.             closedList.Add(currentTile);
  57.  
  58.             foreach (Tile neighbour in GetNeighbourList(currentTile))
  59.             {
  60.                 if (closedList.Contains(neighbour))
  61.                     continue;
  62.  
  63.                 if (!neighbour.IsWalkable())
  64.                 {
  65.                     closedList.Add(neighbour);
  66.                     continue;
  67.                 }
  68.  
  69.                 int tentativeGCost = currentTile.gCost + CalculateDistanceCost(currentTile, neighbour);
  70.                 //Debug.Log(tentativeGCost);
  71.  
  72.                 if (tentativeGCost >= movementPoints)
  73.                     return CalculatePath(currentTile);
  74.  
  75.                 if (tentativeGCost < neighbour.gCost)
  76.                 {
  77.                     neighbour.cameFromTile = currentTile;
  78.                     neighbour.gCost = tentativeGCost;
  79.                     neighbour.hCost = CalculateDistanceCost(neighbour, endTile);
  80.  
  81.                     if (!openList.Contains(neighbour))
  82.                         openList.Add(neighbour);
  83.                 }
  84.             }
  85.         }
  86.  
  87.         return null;
  88.     }
  89.  
  90.     private List<Tile> GetNeighbourList(Tile tile)
  91.     {
  92.         List<Tile> neighbours = new List<Tile>();
  93.  
  94.         if (tile.X - 1 >= 0)
  95.         {
  96.             // left
  97.             neighbours.Add(GetNode(tile.X - 1, tile.Y));
  98.  
  99.             // left down
  100.             if (tile.Y - 1 >= 0)
  101.                 neighbours.Add(GetNode(tile.X - 1, tile.Y - 1));
  102.  
  103.             // left up
  104.             if (tile.Y + 1 < grid.GridSizeY)
  105.                 neighbours.Add(GetNode(tile.X - 1, tile.Y + 1));
  106.         }
  107.  
  108.         if (tile.X+1 < grid.GridSizeX)
  109.         {
  110.             // right
  111.             neighbours.Add(GetNode(tile.X + 1, tile.Y));
  112.  
  113.             // right down
  114.             if (tile.Y - 1 >= 0)
  115.                 neighbours.Add(GetNode(tile.X + 1, tile.Y - 1));
  116.  
  117.             // right up
  118.             if (tile.Y + 1 < grid.GridSizeY)
  119.                 neighbours.Add(GetNode(tile.X + 1, tile.Y + 1));
  120.         }
  121.  
  122.         // down
  123.         if (tile.Y - 1 >= 0)
  124.             neighbours.Add(GetNode(tile.X, tile.Y - 1));
  125.  
  126.         // up
  127.         if (tile.Y + 1 > grid.GridSizeY)
  128.             neighbours.Add(GetNode(tile.X, tile.Y + 1));
  129.  
  130.         return neighbours;
  131.     }
  132.  
  133.     private Tile GetNode(int x, int y)
  134.     {
  135.         return grid.GetGridObject(x, y);
  136.     }
  137.  
  138.     private List<Tile> CalculatePath(Tile endTile)
  139.     {
  140.         List<Tile> path = new List<Tile>();
  141.         path.Add(endTile);
  142.  
  143.         Tile current = endTile;
  144.         while (current.cameFromTile != null)
  145.         {
  146.             path.Add(current.cameFromTile);
  147.             current = current.cameFromTile;
  148.         }
  149.  
  150.         path.Reverse();
  151.  
  152.         return path;
  153.     }
  154.  
  155.     private Tile GetLowestFCostNode(List<Tile> pathList)
  156.     {
  157.         Tile lowersFCostTile = pathList[0];
  158.         for (int i = 1; i < pathList.Count; i++)
  159.             if (pathList[i].fCost < lowersFCostTile.fCost)
  160.                 lowersFCostTile = pathList[i];
  161.  
  162.         return lowersFCostTile;
  163.     }
  164.  
  165.     private int CalculateDistanceCost(Tile a, Tile b)
  166.     {
  167.         int xDistance = Mathf.Abs(a.X - b.X);
  168.         int yDistance = Mathf.Abs(a.Y - b.Y);
  169.         int remaining = Mathf.Abs(xDistance - yDistance);
  170.  
  171.         return MOVE_DIAGONAL_COST * Mathf.Min(xDistance, yDistance) + MOVE_STRAIGHT_COST * remaining;
  172.     }
  173. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement