public void MoveUnit() { AttackUnit = null; if (path.Count == 0) { return; } List <HexCell> move = new List <HexCell>(); move.Add(path[0]); int cellNumber = 1; while (movementLeft > 0 && path.Count > 1) { if (path.Count > cellNumber) { int movementCost = HexUnit.GetMoveCost(path[cellNumber - 1], path[cellNumber], path[cellNumber - 1].GetNeighborDirection(path[cellNumber]), true); if (movementCost == -1 || movementCost > movementLeft) { break; } else { move.Add(path[cellNumber]); movementLeft -= movementCost; cellNumber++; } } else { break; } } if (move.Count > 1) { AttackUnit = null; AttackCity = null; City city = move[move.Count - 1].City; if (city && hexUnit.HexUnitType == HexUnit.UnitType.COMBAT && GetCityState() != city.GetCityState()) { AttackCity = city; CombatSystem.CityFight(this, city); SetMovementLeft(0); } else { HexUnit unitToFight = move[move.Count - 1].GetFightableUnit(HexUnit); if (unitToFight) { AttackUnit = unitToFight; CombatSystem.UnitFight(this, unitToFight.GetComponent <Unit>()); SetMovementLeft(0); } } path.RemoveRange(0, move.Count - 1); HexUnit.Travel(move); } }
bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; } if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if ( neighbor == null || neighbor.SearchPhase > searchFrontierPhase ) { continue; } //if ( neighbor.IsUnderwater || neighbor.Unit ) { // continue; //} //HexEdgeType edgeType = current.GetEdgeType(neighbor); //if ( edgeType == HexEdgeType.Cliff ) { // continue; //} //int moveCost; //if ( current.HasRoadThroughEdge(d) ) { // moveCost = 1; //} //else if(current.Walled != neighbor.Walled ) { // continue; //} //else { // moveCost = ( edgeType == HexEdgeType.Flat ? 5 : 10 ); // moveCost += neighbor.UrbanLevel + neighbor.FarmLevel + neighbor.PlantLevel; //} if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
/// <summary> /// 搜索 /// </summary> /// <param name="fromCell">来的cell</param> /// <param name="toCell">要去的cell</param> /// <param name="unit">要移动的单位</param> /// <returns>是否可以寻路</returns> private /*IEnumerator*/ bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } /*foreach (var nowCell in cells) * { * if (nowCell != fromCell && nowCell != toCell) * { * nowCell.DisableHighlight(); * } * * nowCell.SetLabel(null); * }*/ fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { //yield return delay; var current = searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } var currentTurn = (current.Distance - 1) / speed; for (var d = HexDirection.NE; d <= HexDirection.NW; d++) { var neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } var distance = current.Distance + moveCost; var turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates .DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (neighbor.Distance > distance) { var oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } //coroutine = null; return(false); }
bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); // 遍历未访问的边界格子 while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; // +1,由待访问阶段,进入到已访问阶段 // 判断是否找到目标格子 if (current == toCell) { return(true); } int currentTurn = (current.Distance - 1) / speed; // 到达当前格子所需的回合数 // 把当前格子未访问的可达邻居全部加到待访问格子里 for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) // 跳过对应方向没有邻居的或已经找到最短路径的单元格 { continue; } if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); // 当前格子到邻居的移动成本 if (moveCost < 0) { continue; } int distance = current.Distance + moveCost; int turn = (distance - 1) / speed; // 用刚得到的邻居距离,算出起点出到达邻居所需的回合数, -1是为了避免distance与speed相同时,得到turn为1,但其实本回合就能到达 // 判断该邻居是否在下一个回合才能到达 if (turn > currentTurn) { distance = turn * speed + moveCost; // 不直接使用上面distance的原因是,当前回合剩余行动点在下一回合会清零,所以到达该邻居实际上的移动成本更高 } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.Coordinates.DistanceTo(toCell.Coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
/// <summary> /// Поиск пути /// </summary> /// <param name="fromCell"></param> /// <param name="toCell"></param> /// <returns></returns> bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; searchFrontierPhase += 2; if (searchFrontier == null) { searchFrontier = new HexCellPriorityQueue(); } else { searchFrontier.Clear(); } fromCell.SearchPhase = searchFrontierPhase; fromCell.Distance = 0; searchFrontier.Enqueue(fromCell); while (searchFrontier.Count > 0) { HexCell current = searchFrontier.Dequeue(); current.SearchPhase += 1; //выход из подпрограммы, если достигнута клетка, путь до которой нужно найти и подсветка пути if (current == toCell) { return(true); } //Сколько ходов требуется для достижения клетки(не той, которая выделена) int currentTurn = (current.Distance - 1) / speed; // Поиск в ширину for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = current.GetNeighbor(d); //если соседа нет или есть еще не достигнутые клетки, то в первую очередь обходим их if (neighbor == null || neighbor.SearchPhase > searchFrontierPhase) { continue; } if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } //расстояние до клетки назначения int distance = current.Distance + moveCost; //кол-во ходов до клетки назначения int turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < searchFrontierPhase) { neighbor.SearchPhase = searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { int oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; searchFrontier.Change(neighbor, oldPriority); } } } return(false); }
void Search(HexCell fromCell, HexCell toCell, HexUnit hexUnit, List <HexCell> results) { m_currentPathFrom = fromCell; m_currentPathTo = toCell; int speed = hexUnit.Speed; m_searchFrontierPhase = 2; ClearPath(); ResetSearchPhase(); for (int i = 0; i < m_cells.Count; i++) { m_cells[i].SetLabel(null); m_cells[i].DisableHighlight(); } WaitForSeconds delay = new WaitForSeconds(1 / 60f); fromCell.Distance = 0; fromCell.SearchPhase = m_searchFrontierPhase; m_searchQueue.Enqueue(fromCell); while (m_searchQueue.Count > 0) { //yield return delay;s HexCell current = m_searchQueue.Dequeue(); current.SearchPhase += 1; if (current == toCell) { BuildFinalPath(fromCell, toCell); if (results != null && m_finalPath.Count > 0) { results.AddRange(m_finalPath); } break; } int currentTurn = (current.Distance - 1) / speed; for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++) { HexCell neighbour = current.GetNeighbour(dir); if (neighbour == null || neighbour.SearchPhase > m_searchFrontierPhase) { continue; } if (!hexUnit.IsValidDestination(neighbour)) { continue; } int moveCost = hexUnit.GetMoveCost(current, neighbour, dir); if (moveCost < 0) { continue; } int distance = current.Distance; int newDistance = distance + moveCost; int turn = (newDistance - 1) / speed; if (turn > currentTurn) { newDistance = (turn * speed) + moveCost; } if (neighbour.SearchPhase < m_searchFrontierPhase) { neighbour.SearchPhase = m_searchFrontierPhase; neighbour.Distance = newDistance; SetPathCurrentNext(current, neighbour); neighbour.SearchHeuristic = neighbour.Coordinates.DistanceTo(toCell.Coordinates); m_searchQueue.Enqueue(neighbour); } else if (newDistance < neighbour.Distance) { neighbour.Distance = newDistance; SetPathCurrentNext(current, neighbour); m_searchQueue.Change(neighbour); } } } //for (int i = 0; i < m_cells.Count; i++) //{ // yield return delay; // m_cells[i].Distance = cell.Coordinates.DistanceTo(m_cells[i].Coordinates); //} }
private bool Search(HexCell fromCell, HexCell toCell, HexUnit unit) { int speed = unit.Speed; this.searchFrontierPhase += 2; if (this.searchFrontier == null) { this.searchFrontier = new HexCellPriorityQueue(); } else { this.searchFrontier.Clear(); } fromCell.EnableHighlight(Color.blue); fromCell.SearchPhase = this.searchFrontierPhase; fromCell.Distance = 0; this.searchFrontier.Enqueue(fromCell); while (this.searchFrontier.Count > 0) { var current = this.searchFrontier.Dequeue(); current.SearchPhase += 1; if (current == toCell) { return(true); } var currentTurn = (current.Distance - 1) / speed; for (var d = HexDirection.NE; d <= HexDirection.NW; d++) { var neighbor = current.GetNeighbor(d); if ((neighbor == null) || (neighbor.SearchPhase > this.searchFrontierPhase) || neighbor.Unit) { continue; } if (!unit.IsValidDestination(neighbor)) { continue; } int moveCost = unit.GetMoveCost(current, neighbor, d); if (moveCost < 0) { continue; } var distance = current.Distance + moveCost; var turn = (distance - 1) / speed; if (turn > currentTurn) { distance = turn * speed + moveCost; } if (neighbor.SearchPhase < this.searchFrontierPhase) { neighbor.SearchPhase = this.searchFrontierPhase; neighbor.Distance = distance; neighbor.PathFrom = current; neighbor.SearchHeuristic = neighbor.coordinates.DistanceTo(toCell.coordinates); this.searchFrontier.Enqueue(neighbor); } else if (distance < neighbor.Distance) { var oldPriority = neighbor.SearchPriority; neighbor.Distance = distance; neighbor.PathFrom = current; this.searchFrontier.Change(neighbor, oldPriority); } } } return(false); }