//call during a serach to scan through neighbour, check their score against the position passed //process walkable neighbours only, used to search for a walkable path via A* public void ProcessWalkableNeighbour(Tile targetTile) { for (int i = 0; i < neighbourList.Count; i++) { TileAStar neighbour = neighbourList[i].aStar; if ((neighbour.tile.unit == null) || neighbour.tile == targetTile) { //if the neightbour state is clean (never evaluated so far in the search) if (neighbour.listState == _AStarListState.Unassigned) { //check the score of G and H and update F, also assign the parent to currentNode neighbour.scoreG = scoreG + 1; neighbour.scoreH = Vector3.Distance(neighbour.tile.GetPos(), targetTile.GetPos()); neighbour.UpdateScoreF(); neighbour.parent = tile; } //if the neighbour state is open (it has been evaluated and added to the open list) else if (neighbour.listState == _AStarListState.Open) { //calculate if the path if using this neighbour node through current node would be shorter compare to previous assigned parent node tempScoreG = scoreG + 1; if (neighbour.scoreG > tempScoreG) { //if so, update the corresponding score and and reassigned parent neighbour.parent = tile; neighbour.scoreG = tempScoreG; neighbour.UpdateScoreF(); } } } } }
public void AutoDeployFaction(int factionID = -1) { List <Unit> unitList = factionList[factionID].startingUnitList; List <Tile> tileList = TileManager.GetDeployableTileList(factionList[factionID].ID); for (int i = 0; i < tileList.Count; i++) { if (!tileList[i].walkable || tileList[i].unit != null) { tileList.RemoveAt(i); i -= 1; } } int count = 0; for (int i = 0; i < unitList.Count; i++) { if (tileList.Count == 0) { break; } Unit unit = unitList[i]; int rand = Random.Range(0, tileList.Count); Tile tile = tileList[rand]; tileList.RemoveAt(rand); tile.unit = unit; unit.tile = tile; unit.transform.position = tile.GetPos(); unit.gameObject.SetActive(true); unit.factionID = factionList[factionID].ID; factionList[i].allUnitList.Add(unit); count += 1; } for (int i = 0; i < count; i++) { unitList.RemoveAt(0); } }
void _NewHoveredTile(Tile tile) { _ClearHoveredTile(); ShowIndicator(tile.GetPos()); }
//search for a path, through walkable tile only //for normal movement, return the path in a list of hexTile public static List <Tile> SearchWalkableTile(byte[,] costMap, Tile originTile, Tile destTile) { List <Tile> closeList = new List <Tile>(); List <Tile> openList = new List <Tile>(); Tile currentTile = originTile; float currentLowestF = Mathf.Infinity; int id = 0; int i = 0; while (true) { //if we have reach the destination if (currentTile == destTile) { break; } //move currentNode to closeList; closeList.Add(currentTile); currentTile.aStar.listState = TileAStar._AStarListState.Close; //loop through the neighbour of current loop, calculate score and stuff currentTile.aStar.ProcessWalkableNeighbour(destTile); //put all neighbour in openlist foreach (Tile neighbour in currentTile.aStar.GetNeighbourList(true)) { if ( neighbour.x > costMap.GetUpperBound(0) || neighbour.y > costMap.GetUpperBound(1) || costMap[neighbour.x, neighbour.y] == 255 || neighbour.unit != null) { continue; } if (neighbour.aStar.listState == TileAStar._AStarListState.Unassigned || neighbour == destTile) { //~ //set the node state to open neighbour.aStar.listState = TileAStar._AStarListState.Open; openList.Add(neighbour); } } //clear the current node, before getting a new one, so we know if there isnt any suitable next node 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 there's no node left in openlist, path doesnt exist if (currentTile == null) { break; } openList.RemoveAt(id); } if (currentTile == null) { float tileSize = TileManager.GetTileSize() * TileManager.GetGridToTileSizeRatio(); currentLowestF = Mathf.Infinity; for (i = 0; i < closeList.Count; i++) { float dist = Vector3.Distance(destTile.GetPos(), closeList[i].GetPos()); if (dist < currentLowestF) { currentLowestF = dist; currentTile = closeList[i]; if (dist < tileSize * 1.5f) { break; } } } } List <Tile> path = new List <Tile>(); while (currentTile != null) { if (currentTile == originTile || currentTile == currentTile.aStar.parent) { break; } path.Add(currentTile); currentTile = currentTile.aStar.parent; } path = InvertTileArray(path); ResetGraph(destTile, openList, closeList); return(path); }
public IEnumerator MoveRoutine(Tile targetTile) { tile.unit = null; byte[,] grid = TileManager.GetTiledMap().GetCostGrid(TileManager.TerrainToCost); List <Tile> path = AStar.SearchWalkableTile(grid, tile, targetTile); while (!TurnControl.ClearToProceed()) { yield return(null); } TurnControl.ActionCommenced(); if (unitAnim != null) { unitAnim.Move(); } if (unitAudio != null) { unitAudio.Move(); } while (path.Count > 0) { while (true) { float dist = Vector3.Distance(transform.position, path[0].GetPos()); if (dist < 0.05f) { break; } //Quaternion wantedRot = Quaternion.LookRotation(path[0].GetPos() - transform.position); //transform.rotation = Quaternion.Slerp(transform.rotation, wantedRot, Time.deltaTime * moveSpeed * 3); unitAnim.Direction(path[0].GetPos().x - transform.position.x, path[0].GetPos().y - transform.position.y); Vector3 dir = (path[0].GetPos() - transform.position).normalized; transform.Translate(dir * Mathf.Min(moveSpeed * Time.deltaTime, dist), Space.World); yield return(null); } tile = path[0]; //FactionManager.UpdateHostileUnitTriggerStatus(this); path.RemoveAt(0); } if (unitAnim != null) { unitAnim.StopMove(); } tile.unit = this; transform.position = tile.GetPos(); TurnControl.ActionCompleted(0.15f); BattleControl.UnlockUnitSelect(); FinishAction(); }