Advertisement
Guest User

Untitled

a guest
Oct 28th, 2016
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.45 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. public class Grid
  5. {
  6.     public static Grid Instance;
  7.     public NodeElement[,] nodes;
  8.     public int width, height;
  9.     public Grid(int _width = 0, int _height = 0)
  10.     {
  11.         Instance = this;
  12.         width = _width;
  13.         height = _height;
  14.         nodes = new NodeElement[width, height];
  15.         for (int x = 0; x < width; x++)
  16.         {
  17.             for (int y = 0; y < height; y++)
  18.             {
  19.                 nodes[x, y] = new NodeElement(x, y, 0, true);
  20.             }
  21.         }
  22.     }
  23.     public bool WithinBounds(int x, int y)
  24.     {
  25.         return x >= 0 && x < width && y >= 0 && y < height;
  26.     }
  27.     public bool WithinBounds(NodeElement p)
  28.     {
  29.         return WithinBounds(p.x, p.y);
  30.     }
  31.     public static NodeElement GetNodeAt(int x, int y)
  32.     {
  33.         if (Instance.WithinBounds(x, y))
  34.         {
  35.             return Instance.nodes[x, y];
  36.         }
  37.         return null;
  38.     }
  39.     public static bool IsWalkableAt(int x, int y)
  40.     {
  41.         NodeElement temp = GetNodeAt(x, y);
  42.         if (temp != null)
  43.         {
  44.             return temp.passable;
  45.         }
  46.         return false;
  47.     }
  48.     public List<NodeElement> openList;
  49.     NodeElement _start, _goal;
  50.     public static List<NodeElement> Path(NodeElement start, NodeElement goal)
  51.     {
  52.         Instance._start = start;
  53.         Instance._goal = goal;
  54.         List<NodeElement> _path = new List<NodeElement>();
  55.         NodeElement tNode;
  56.         // set the `g` and `f` value of the start node to be 0
  57.         start.costSofar = 0;
  58.         start.heuristicStartToEndLen = 0;
  59.  
  60.         // push the start node into the open list
  61.         _path.Add(start);
  62.         start.isOpened = true;
  63.  
  64.         // while the open list is not empty
  65.         while (_path.Count > 0)
  66.         {
  67.             // pop the position of node which has the minimum `f` value.
  68.             _path.Sort();
  69.             tNode = _path[_path.Count - 1];
  70.             _path.RemoveAt(_path.Count - 1);
  71.             //tNode.isClosed = true;
  72.  
  73.             if (tNode == goal)
  74.             {
  75.                 return NodeElement.Backtrace(tNode); // rebuilding path
  76.             }
  77.  
  78.             identifySuccessors(tNode);
  79.         }
  80.  
  81.         return _path;
  82.     }
  83.     public static float Euclidean(int iDx, int iDy)
  84.     {
  85.         float tFdx = (float)iDx;
  86.         float tFdy = (float)iDy;
  87.         return (float)Mathf.Sqrt(tFdx * tFdx + tFdy * tFdy);
  88.     }
  89.     private static void identifySuccessors(NodeElement iNode)
  90.     {
  91.         List<NodeElement> tOpenList = Instance.openList;
  92.         int tEndX = Instance._goal.x;
  93.         int tEndY = Instance._goal.y;
  94.         NodeElement tNeighbor;
  95.         NodeElement tJumpNode;
  96.  
  97.         List<NodeElement> tNeighbors = findNeighbors(iNode);
  98.         for (int i = 0; i < tNeighbors.Count; i++)
  99.         {
  100.             tNeighbor = tNeighbors[i];
  101.             tJumpNode = jump(tNeighbor.x, tNeighbor.y, iNode.x, iNode.y);
  102.             if (tJumpNode != null)
  103.             {
  104.                 tJumpNode = GetNodeAt(tJumpNode.x, tJumpNode.y);
  105.                 // include distance, as parent may not be immediately adjacent:
  106.                 float tCurNodeToJumpNodeLen = Euclidean(Mathf.Abs(tJumpNode.x - iNode.x), Mathf.Abs(tJumpNode.y - iNode.y));
  107.                 float tStartToJumpNodeLen = (float)iNode.costSofar + tCurNodeToJumpNodeLen; // next `startToCurNodeLen` value
  108.  
  109.                 if (!tJumpNode.isOpened || tStartToJumpNodeLen < tJumpNode.startToCurNodeLen)
  110.                 {
  111.                     tJumpNode.startToCurNodeLen = tStartToJumpNodeLen;
  112.                     tJumpNode.heuristicStartToEndLen = tJumpNode.startToCurNodeLen + tJumpNode.heuristicCurNodeToEndLen;
  113.                     tJumpNode.cameFrom = iNode;
  114.  
  115.                     if (!tJumpNode.isOpened)
  116.                     {
  117.                         tOpenList.Add(tJumpNode);
  118.                         tJumpNode.isOpened = true;
  119.                     }
  120.                 }
  121.             }
  122.         }
  123.     }
  124.     private static List<NodeElement> findNeighbors(NodeElement iNode)
  125.     {
  126.         NodeElement tParent = iNode.cameFrom;
  127.         int tX = iNode.x;
  128.         int tY = iNode.y;
  129.         int tPx, tPy, tDx, tDy;
  130.         List<NodeElement> tNeighborNodes = new List<NodeElement>();
  131.         NodeElement tNeighborNode;
  132.  
  133.         // directed pruning: can ignore most neighbors, unless forced.
  134.         if (tParent != null)
  135.         {
  136.             tPx = tParent.x;
  137.             tPy = tParent.y;
  138.             // get the normalized direction of travel
  139.             tDx = (tX - tPx) / Mathf.Max(Mathf.Abs(tX - tPx), 1);
  140.             tDy = (tY - tPy) / Mathf.Max(Mathf.Abs(tY - tPy), 1);
  141.  
  142.             {
  143.                 // search diagonally
  144.                 if (tDx != 0 && tDy != 0)
  145.                 {
  146.                     if (IsWalkableAt(tX, tY + tDy))
  147.                     {
  148.                         tNeighborNodes.Add(GetNodeAt(tX, tY + tDy));
  149.                     }
  150.                     if (IsWalkableAt(tX + tDx, tY))
  151.                     {
  152.                         tNeighborNodes.Add(GetNodeAt(tX + tDx, tY));
  153.                     }
  154.  
  155.                     if (IsWalkableAt(tX + tDx, tY + tDy))
  156.                     {
  157.                         if (IsWalkableAt(tX, tY + tDy) && IsWalkableAt(tX + tDx, tY))
  158.                             tNeighborNodes.Add(GetNodeAt(tX + tDx, tY + tDy));
  159.                     }
  160.  
  161.                     if (IsWalkableAt(tX - tDx, tY + tDy))
  162.                     {
  163.                         if (IsWalkableAt(tX, tY + tDy) && IsWalkableAt(tX - tDx, tY))
  164.                             tNeighborNodes.Add(GetNodeAt(tX - tDx, tY + tDy));
  165.                     }
  166.  
  167.                     if (IsWalkableAt(tX + tDx, tY - tDy))
  168.                     {
  169.                         if (IsWalkableAt(tX, tY - tDy) && IsWalkableAt(tX + tDx, tY))
  170.                             tNeighborNodes.Add(GetNodeAt(tX + tDx, tY - tDy));
  171.                     }
  172.  
  173.  
  174.                 }
  175.                 // search horizontally/vertically
  176.                 else
  177.                 {
  178.                     if (tDx == 0)
  179.                     {
  180.                         if (IsWalkableAt(tX, tY + tDy))
  181.                         {
  182.                             tNeighborNodes.Add(GetNodeAt(tX, tY + tDy));
  183.  
  184.                             if (IsWalkableAt(tX + 1, tY + tDy) && IsWalkableAt(tX + 1, tY))
  185.                             {
  186.                                 tNeighborNodes.Add(GetNodeAt(tX + 1, tY + tDy));
  187.                             }
  188.                             if (IsWalkableAt(tX - 1, tY + tDy) && IsWalkableAt(tX - 1, tY))
  189.                             {
  190.                                 tNeighborNodes.Add(GetNodeAt(tX - 1, tY + tDy));
  191.                             }
  192.                         }
  193.                         if (IsWalkableAt(tX + 1, tY))
  194.                             tNeighborNodes.Add(GetNodeAt(tX + 1, tY));
  195.                         if (IsWalkableAt(tX - 1, tY))
  196.                             tNeighborNodes.Add(GetNodeAt(tX - 1, tY));
  197.                     }
  198.                     else
  199.                     {
  200.                         if (IsWalkableAt(tX + tDx, tY))
  201.                         {
  202.  
  203.                             tNeighborNodes.Add(GetNodeAt(tX + tDx, tY));
  204.  
  205.                             if (IsWalkableAt(tX + tDx, tY + 1) && IsWalkableAt(tX, tY + 1))
  206.                             {
  207.                                 tNeighborNodes.Add(GetNodeAt(tX + tDx, tY + 1));
  208.                             }
  209.                             if (IsWalkableAt(tX + tDx, tY - 1) && IsWalkableAt(tX, tY - 1))
  210.                             {
  211.                                 tNeighborNodes.Add(GetNodeAt(tX + tDx, tY - 1));
  212.                             }
  213.                         }
  214.                         if (IsWalkableAt(tX, tY + 1))
  215.                             tNeighborNodes.Add(GetNodeAt(tX, tY + 1));
  216.                         if (IsWalkableAt(tX, tY - 1))
  217.                             tNeighborNodes.Add(GetNodeAt(tX, tY - 1));
  218.                     }
  219.                 }
  220.             }
  221.  
  222.         }
  223.         // return all neighbors
  224.         else
  225.         {
  226.             tNeighborNodes = GetNeighbors(iNode);
  227.             for (int i = 0; i < tNeighborNodes.Count; i++)
  228.             {
  229.                 tNeighborNode = tNeighborNodes[i];
  230.                 tNeighborNodes.Add(GetNodeAt(tNeighborNode.x, tNeighborNode.y));
  231.             }
  232.         }
  233.  
  234.         return tNeighborNodes;
  235.     }
  236.     public static List<NodeElement> GetNeighbors(NodeElement iNode)
  237.     {
  238.         int tX = iNode.x;
  239.         int tY = iNode.y;
  240.         List<NodeElement> neighbors = new List<NodeElement>();
  241.         bool tS0 = false, tD0 = false,
  242.             tS1 = false, tD1 = false,
  243.             tS2 = false, tD2 = false,
  244.             tS3 = false, tD3 = false;
  245.         int x = tX, y = tY - 1;
  246.         if (IsWalkableAt(tX, tY))
  247.         {
  248.             neighbors.Add(GetNodeAt(x, y));
  249.             tS0 = true;
  250.         }
  251.         x = tX + 1; y = tY;
  252.         if (IsWalkableAt(x, y))
  253.         {
  254.             neighbors.Add(GetNodeAt(x, y));
  255.             tS1 = true;
  256.         }
  257.         x = tX; y = tY + 1;
  258.         if (IsWalkableAt(x, y))
  259.         {
  260.             neighbors.Add(GetNodeAt(x, y));
  261.             tS2 = true;
  262.         }
  263.         x = tX - 1; y = tY;
  264.         if (IsWalkableAt(x, y))
  265.         {
  266.             neighbors.Add(GetNodeAt(x, y));
  267.             tS3 = true;
  268.         }
  269.  
  270.         tD0 = tS3 && tS0;
  271.         tD1 = tS0 && tS1;
  272.         tD2 = tS1 && tS2;
  273.         tD3 = tS2 && tS3;
  274.  
  275.  
  276.         x = tX - 1; y = tY - 1;
  277.         if (tD0 && IsWalkableAt(x, y))
  278.         {
  279.             neighbors.Add(GetNodeAt(x, y));
  280.         }
  281.         x = tX + 1; y = tY - 1;
  282.         if (tD1 && IsWalkableAt(x, y))
  283.         {
  284.             neighbors.Add(GetNodeAt(x, y));
  285.         }
  286.         x = tX + 1; y = tY + 1;
  287.         if (tD2 && IsWalkableAt(x, y))
  288.         {
  289.             neighbors.Add(GetNodeAt(x, y));
  290.         }
  291.         x = tX - 1; y = tY + 1;
  292.         if (tD3 && IsWalkableAt(x, y))
  293.         {
  294.             neighbors.Add(GetNodeAt(x, y));
  295.         }
  296.         return neighbors;
  297.     }
  298.     private static NodeElement jump(int iX, int iY, int iPx, int iPy)
  299.     {
  300.         if (!IsWalkableAt(iX, iY))
  301.         {
  302.             return null;
  303.         }
  304.         else if (GetNodeAt(iX, iY) == Instance._goal)
  305.         {
  306.             return Instance._goal;
  307.         }
  308.  
  309.         int tDx = iX - iPx;
  310.         int tDy = iY - iPy;
  311.         NodeElement jx = null;
  312.         NodeElement jy = null;
  313.         {
  314.             // check for forced neighbors
  315.             // along the diagonal
  316.             if (tDx != 0 && tDy != 0)
  317.             {
  318.                 if ((IsWalkableAt(iX + tDx, iY + tDy) && IsWalkableAt(iX, iY + tDy) && !IsWalkableAt(iX + tDx, iY)) ||
  319.                     (IsWalkableAt(iX + tDx, iY + tDy) && IsWalkableAt(iX + tDx, iY) && !IsWalkableAt(iX, iY + tDy)))
  320.                 {
  321.                     return GetNodeAt(iX, iY);
  322.                 }
  323.             }
  324.             // horizontally/vertically
  325.             else
  326.             {
  327.                 if (tDx != 0)
  328.                 {
  329.                     // moving along x
  330.                     if ((IsWalkableAt(iX, iY + 1) && !IsWalkableAt(iX - tDx, iY + 1)) ||
  331.                         (IsWalkableAt(iX, iY - 1) && !IsWalkableAt(iX - tDx, iY - 1)))
  332.                     {
  333.                         return GetNodeAt(iX, iY);
  334.                     }
  335.                 }
  336.                 else
  337.                 {
  338.                     if ((IsWalkableAt(iX + 1, iY) && !IsWalkableAt(iX + 1, iY - tDy)) ||
  339.                         (IsWalkableAt(iX - 1, iY) && !IsWalkableAt(iX - 1, iY - tDy)))
  340.                     {
  341.                         return GetNodeAt(iX, iY);
  342.                     }
  343.                 }
  344.             }
  345.  
  346.  
  347.             // when moving diagonally, must check for vertical/horizontal jump points
  348.             if (tDx != 0 && tDy != 0)
  349.             {
  350.                 jx = jump(iX + tDx, iY, iX, iY);
  351.                 jy = jump(iX, iY + tDy, iX, iY);
  352.                 if (jx != null || jy != null)
  353.                 {
  354.                     return GetNodeAt(iX, iY);
  355.                 }
  356.             }
  357.  
  358.             // moving diagonally, must make sure both of the vertical/horizontal
  359.             // neighbors is open to allow the path
  360.             if (IsWalkableAt(iX + tDx, iY) && IsWalkableAt(iX, iY + tDy))
  361.             {
  362.                 return jump(iX + tDx, iY + tDy, iX, iY);
  363.             }
  364.             else
  365.             {
  366.                 return null;
  367.             }
  368.         }
  369.  
  370.     }
  371.  
  372. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement