226 lines
6.3 KiB
C#
226 lines
6.3 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace TBTK{
|
|
|
|
public class AStar{
|
|
|
|
public enum _BypassUnit{ No, FriendlyOnly, All }
|
|
|
|
public static int BypassUnitCode(Unit unit){
|
|
if(unit.canMovePastUnit==_BypassUnit.No) return -1;
|
|
else if(unit.canMovePastUnit==_BypassUnit.All) return -2;
|
|
else return unit.facID;
|
|
}
|
|
public static int BypassUnitCode(bool bypassUnit){
|
|
return bypassUnit ? -2 : -1 ;
|
|
}
|
|
|
|
public static bool IgnoreAllUnit(int flag){ return flag==-2; }
|
|
public static bool CantBypassUnit(int flag){ return flag==-1; }
|
|
public static bool BypassFriendlyUnit(int flag){ return flag>=0; }
|
|
|
|
|
|
//search for a path, through walkable tile only
|
|
//for normal movement, return the path in a list of hexTile
|
|
//public static List<Node> SearchWalkableNode(Node originNode, Node destNode, bool returnNearest=true){
|
|
//~ public static List<Node> SearchWalkableNode(Node originNode, Node destNode, bool bypassUnit=true, bool bypassObs=true, bool returnNearest=true){
|
|
//~ return SearchWalkableNode(originNode, destNode, BypassUnitCode(bypassUnit), bypassObs, returnNearest);
|
|
//~ }
|
|
public static List<Node> SearchWalkableNode(Node originNode, Node destNode, int bypassUnit=-1, bool bypassObs=true, bool returnNearest=true){
|
|
|
|
GridManager.ResetGrid();
|
|
|
|
List<Node> closeList=new List<Node>();
|
|
List<Node> openList=new List<Node>();
|
|
|
|
Node currentNode=originNode;
|
|
|
|
float currentLowestF=Mathf.Infinity;
|
|
int id=0;
|
|
int i=0;
|
|
|
|
while(true){
|
|
|
|
//if we have reach the destination
|
|
if(currentNode==destNode) break;
|
|
|
|
//move currentNode to closeList;
|
|
closeList.Add(currentNode);
|
|
currentNode.listState=Node._ListState.Close;
|
|
|
|
//loop through the neighbour of current loop, calculate score and stuff
|
|
currentNode.ProcessNeighbour(destNode.GetPos(), bypassUnit, bypassObs);
|
|
|
|
//put all neighbour in openlist
|
|
foreach(Node neighbour in currentNode.GetNeighbourList(true, bypassUnit, bypassObs)){
|
|
if(neighbour.IsBlocked(currentNode, bypassUnit, bypassObs)) continue;
|
|
if(neighbour.listState==Node._ListState.Unassigned || neighbour==destNode){
|
|
//~ //set the node state to open
|
|
neighbour.listState=Node._ListState.Open;
|
|
openList.Add(neighbour);
|
|
}
|
|
}
|
|
|
|
//clear the current node, before getting a new one, so we know if there isnt any suitable next node
|
|
currentNode=null;
|
|
|
|
|
|
currentLowestF=Mathf.Infinity;
|
|
id=0;
|
|
for(i=0; i<openList.Count; i++){
|
|
if(openList[i]==destNode){
|
|
currentNode=openList[i];
|
|
id=i; break;
|
|
}
|
|
if(openList[i].scoreF<currentLowestF){
|
|
currentLowestF=openList[i].scoreF;
|
|
currentNode=openList[i];
|
|
id=i;
|
|
}
|
|
}
|
|
|
|
|
|
//if there's no node left in openlist, path doesnt exist
|
|
if(currentNode==null){
|
|
if(!returnNearest) return new List<Node>();
|
|
break;
|
|
}
|
|
|
|
openList.RemoveAt(id);
|
|
}
|
|
|
|
if(currentNode==null){
|
|
float tileSize=GridManager.GetNodeSize();//*GridManager.GetGridToTileSizeRatio();
|
|
currentLowestF=Mathf.Infinity;
|
|
for(i=0; i<closeList.Count; i++){
|
|
float dist=Vector3.Distance(destNode.GetPos(), closeList[i].GetPos());
|
|
if(dist<currentLowestF){
|
|
currentLowestF=dist;
|
|
currentNode=closeList[i];
|
|
if(dist<tileSize*1.5f) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
List<Node> path=new List<Node>();
|
|
while(currentNode!=null){
|
|
if(currentNode==originNode || currentNode==currentNode.parent) break;
|
|
path.Add(currentNode);
|
|
currentNode=currentNode.parent;
|
|
}
|
|
|
|
path=InvertNodeArray(path);
|
|
|
|
ResetGraph(destNode, openList, closeList);
|
|
|
|
return path;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
//search the shortest path through all tile reagardless of status
|
|
//this is used to accurately calculate the distance between 2 tiles in term of tile
|
|
//distance calculated applies for line traverse thru walkable tiles only, otherwise it can be calculated using the coordinate
|
|
public static int GetDistance(Tile srcTile, Tile targetTile){
|
|
List<Tile> closeList=new List<Tile>();
|
|
List<Tile> openList=new List<Tile>();
|
|
|
|
Tile currentTile=srcTile;
|
|
if(srcTile==null) Debug.Log("src tile is null!!!");
|
|
|
|
float currentLowestF=Mathf.Infinity;
|
|
int id=0;
|
|
int i=0;
|
|
|
|
while(true){
|
|
//if we have reach the destination
|
|
if(currentTile==targetTile) break;
|
|
|
|
//move currentNode to closeList;
|
|
closeList.Add(currentTile);
|
|
currentTile.aStar.listState=Node._ListState.Close;
|
|
|
|
//loop through all neighbours, regardless of status
|
|
//currentTile.ProcessAllNeighbours(targetTile);
|
|
currentTile.aStar.ProcessWalkableNeighbour(targetTile);
|
|
|
|
//put all neighbour in openlist
|
|
foreach(Tile neighbour in currentTile.aStar.GetNeighbourList()){
|
|
if(neighbour.unit!=null && neighbour!=targetTile) continue;
|
|
if(neighbour.aStar.listState==Node._ListState.Unassigned) {
|
|
//set the node state to open
|
|
neighbour.aStar.listState=Node._ListState.Open;
|
|
openList.Add(neighbour);
|
|
}
|
|
}
|
|
|
|
currentTile=null;
|
|
|
|
currentLowestF=Mathf.Infinity;
|
|
id=0;
|
|
for(i=0; i<openList.Count; i++){
|
|
if(openList[i].aStar.scoreF<currentLowestF){
|
|
currentLowestF=openList[i].aStar.scoreF;
|
|
currentTile=openList[i];
|
|
id=i;
|
|
}
|
|
}
|
|
|
|
if(currentTile==null) return -1;
|
|
|
|
openList.RemoveAt(id);
|
|
}
|
|
|
|
|
|
int counter=0;
|
|
while(currentTile!=null){
|
|
counter+=1;
|
|
currentTile=currentTile.aStar.parent;
|
|
}
|
|
|
|
ResetGraph(targetTile, openList, closeList);
|
|
|
|
return counter-1;
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
private static List<Vector3> InvertArray(List<Vector3> p){
|
|
List<Vector3> pInverted=new List<Vector3>();
|
|
for(int i=0; i<p.Count; i++){
|
|
pInverted.Add(p[p.Count-(i+1)]);
|
|
}
|
|
return pInverted;
|
|
}
|
|
|
|
private static List<Node> InvertNodeArray(List<Node> p){
|
|
List<Node> pInverted=new List<Node>();
|
|
for(int i=0; i<p.Count; i++){
|
|
pInverted.Add(p[p.Count-(i+1)]);
|
|
}
|
|
return pInverted;
|
|
}
|
|
|
|
|
|
//reset all the tile, called after a search is complete
|
|
private static void ResetGraph(Node hNode, List<Node> oList, List<Node> cList){
|
|
hNode.ResetListState();
|
|
hNode.parent=null;
|
|
|
|
foreach(Node node in oList){
|
|
node.ResetListState();
|
|
node.parent=null;
|
|
}
|
|
foreach(Node node in cList){
|
|
node.ResetListState();
|
|
node.parent=null;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|