public List <PathNode> GetPath(PathNode start, PathNode end) { WaypointManager wg = GameObject.Find("WaypointManager").GetComponent <WaypointManager>(); var sources = wg.pathNodes; if (start == null || end == null) { if (sources != null && sources.Count >= 2) { start = sources[PathNode.startNode] /*.GetComponent<PathNode>()*/; //.GetInnerObject(); end = sources[PathNode.endNode] /*.GetComponent<PathNode>()*/; //.GetInnerObject(); } if (start == null || end == null) { Debug.LogWarning("Need 'start' and or 'end' defined!"); enabled = false; return(null); } } startIndex = Closest(sources, start.position); endIndex = Closest(sources, end.position); return(AStarHelper.Calculate(sources[startIndex] /*.GetComponent<PathNode>()*/, sources[endIndex] /*.GetComponent<PathNode>()*/)); }
internal override Boolean CalculatePath(GridSlot p_start, GridSlot p_target, List <GridSlot> p_pathBuffer) { if (!p_target.CheckForSummons()) { AStarHelper <GridSlot> .Calculate(p_start, p_target, GameConfig.MaxSteps, m_owner, false, true, true, p_pathBuffer); return(p_pathBuffer.Count > 0); } List <GridSlot> list; if (Position.Distance(p_target.Position, LegacyLogic.Instance.WorldManager.Party.Position) <= 1.1f) { list = GetMeleeTargets(LegacyLogic.Instance.MapLoader.Grid, LegacyLogic.Instance.WorldManager.Party); } else { list = GetRangedTargets(LegacyLogic.Instance.MapLoader.Grid, LegacyLogic.Instance.WorldManager.Party); } if (list.FindAll(new Predicate <GridSlot>(FindSlotsWithSummons)).Count == list.Count) { return(base.CalculatePath(p_start, p_target, p_pathBuffer)); } list.RemoveAll(new Predicate <GridSlot>(FindSlotsWithSummons)); list.Sort(new Comparison <GridSlot>(DistSortAsc)); AStarHelper <GridSlot> .Calculate(p_start, list[0], GameConfig.MaxSteps, m_owner, false, true, true, p_pathBuffer); list.Sort(new Comparison <GridSlot>(DistSortAsc)); return(p_pathBuffer.Count > 0); }
public static int Closest(List </*GameObject*/ PathNode> inNodes, Vector3 toPoint) { int closestIndex = 0; float minDist = float.MaxValue; for (int i = 0; i < inNodes.Count; i++) { if (AStarHelper.Invalid(inNodes[i] /*.GetComponent<PathNode>()*/)) { continue; } float thisDist = Vector3.Distance(toPoint, inNodes[i] /*.GetComponent<PathNode>()*/.Position); if (thisDist > minDist) { continue; } minDist = thisDist; closestIndex = i; } if (minDist != float.MaxValue) { return(closestIndex); } else { return(-1); } }
public void EstablishEnemyPositions() { positionToNearestCharacter.Clear(); nearestCharacter.Clear(); var currentRoster = EnemyRosterController.instance.GetCurrentRoster(); var currentCharacters = GameObject.FindGameObjectsWithTag("Player"); foreach (EnemyController enemy in currentRoster) { var pos = new List <GridTile>(); var start = GridController.instance.GetTileAtPosition(enemy.transform.position); foreach (GameObject player in currentCharacters) { if (!player.activeInHierarchy) { continue; } var end = GridController.instance.GetTileAtPosition(player.transform.position); var toChar = AStarHelper.GetPath(start, end, true); Debug.Log("Checking path to " + player.name + " and found path of length " + toChar.Count); if (pos.Count == 0 || pos.Count > toChar.Count) { pos = toChar; nearestCharacter[enemy] = player.GetComponent <PlayerCharacterController>(); } } positionToNearestCharacter[enemy] = pos; } }
//This is always called after the objects have been sorted, use cached position public EnemyAction GetAction() { var positionOfNearestCharacter = FindClosestPlayer().transform.position; //Need to recalculate path as may have changed by previous moves var pathToNearestCharacter = AStarHelper.GetPath( GridController.instance.GetTileAtPosition(transform.position), GridController.instance.GetTileAtPosition(positionOfNearestCharacter) ); var list = pathToNearestCharacter.ConvertAll( new System.Converter <GridTile, Vector2>(GetWorldPositionOfGridTile) ); //Need to find the nearest character and create an int list of positions to move towards if (list.Count > 0) { return(new MoveToTargetPositionAction( gameObject, this, movementStyle, list.GetRange(0, Mathf.Min(availableMove - 1, list.Count)) )); } else { return(new MoveToTargetPositionAction( gameObject, this, movementStyle, list )); } }
public override void CheckVisibility(Boolean skipAnimation) { base.CheckVisibility(skipAnimation); Single num = 0f; if (MyController != null) { Monster monster = (Monster)MyController; Party party = LegacyLogic.Instance.WorldManager.Party; if (party != null && party.HasDangerSense()) { Int32 monsterVisibilityRangeWithDangerSense = ConfigManager.Instance.Game.MonsterVisibilityRangeWithDangerSense; Grid grid = LegacyLogic.Instance.MapLoader.Grid; GridSlot slot = grid.GetSlot(monster.Position); GridSlot slot2 = grid.GetSlot(party.Position); Int32 num2 = AStarHelper <GridSlot> .Calculate(slot, slot2, monsterVisibilityRangeWithDangerSense, null, false, null); if (num2 > 0) { num = 1f; } } else if (party != null && monster.IsAggro && 1f >= Position.DistanceSquared(monster.Position, party.Position)) { num = 1f; } } if (num == 0f) { TooltipManager.Instance.Hide(this); } collider.enabled = (num > 0f); TweenAlpha.Begin(gameObject, (!skipAnimation) ? 1 : 0, num); }
private static Boolean InMoveRange(Grid grid, Position start, Position target, Int32 range) { GridSlot slot = grid.GetSlot(start); GridSlot slot2 = grid.GetSlot(target); Int32 num = AStarHelper <GridSlot> .Calculate(slot, slot2, range, null, false, null); return(num > 0); }
public AStar(AStarHelper aStarHelper, int start, int goal, MZDungeon dungeon) { this.aStarHelper = aStarHelper; this.start = start; this.goal = goal; this.dungeon = dungeon; this.current = start; openSet = new Dictionary <int, float>(); closedSet = new List <int>(); }
internal virtual Boolean CalculatePath(GridSlot p_start, GridSlot p_target, List <GridSlot> p_pathBuffer) { // Avoid to stack agro monsters due to cast of spell or long obstacles Int32 maxSteps = GameConfig.MaxSteps; if (m_owner.IsAggro) { maxSteps *= 3; } return(AStarHelper <GridSlot> .Calculate(p_start, p_target, maxSteps, m_owner, false, p_pathBuffer) > 0); }
/// <summary> /// Generate the level /// </summary> public void Generate() { roadSize = SceneParameters.initialSize; Transform firstChunk, veryLastChunk; GameObject fline; GameObject car = GameObject.Find("Car"); // Initialization rays = new Vector3[6]; hits = new RaycastHit[6]; bool done = false; while (!done) { RemoveAll(); lastRotY = 0.0f; lastIdx = 0; putChunks(gameObject.transform, 0.0f, 0, -1); firstChunk = transform.Find("part-0"); AStarHelper astar = new AStarHelper(firstChunk, this); done = astar.run(); if (!done) { Debug.Log("Trying again"); } //GameObject inicio = GameObject.CreatePrimitive(PrimitiveType.Cylinder); //inicio.transform.position= firstChunk.position ;//- new Vector3(0,0,0.25f*firstChunk.GetComponent<BoxCollider>().size.z); //Debug.Log(transform.position); } firstChunk = transform.Find("part-0"); float carX = (firstChunk.position.x + firstChunk.GetComponent <RoadChunk> ().mountPoint.transform.position.x) / 2; float carZ = (firstChunk.position.z + firstChunk.GetComponent <RoadChunk> ().mountPoint.position.z) / 2; car.transform.position = new Vector3(carX, firstChunk.position.y + 0.01f, carZ); car.transform.rotation = firstChunk.GetComponent <RoadChunk> ().mountPoint.rotation; car.transform.Rotate(new Vector3(0, 180, 0)); //firstChunk.GetComponent<RoadChunk>().mountPoint.rotation.eulerAngles.y /2, 0)); //fline = UnityEngine.Object.Instantiate (FinishLine) as GameObject; //fline.transform.position = new Vector3 (1.5f, 6f, 7f); //fline.transform.rotation = new Quaternion (0, 0, 0, 0); //fline.transform.Rotate (new Vector3 (0, 90, 0)); }
internal Boolean TryMove(List <GridSlot> p_targets, Grid p_grid, GridSlot p_startSlot, Party p_party) { if (m_owner.CombatHandler.CanMove) { List <GridSlot> pathBuffer = m_PathBuffer; GridSlot gridSlot = null; Int32 num = 999; GridSlot gridSlot2 = null; foreach (GridSlot gridSlot3 in p_targets) { pathBuffer.Clear(); if (CalculatePath(p_startSlot, gridSlot3, pathBuffer) && pathBuffer.Count < num) { gridSlot = gridSlot3; num = pathBuffer.Count; gridSlot2 = pathBuffer[1]; } } if (gridSlot != null) { EDirection lineOfSightDirection = EDirectionFunctions.GetLineOfSightDirection(p_startSlot.Position, gridSlot2.Position); if (lineOfSightDirection != EDirection.CENTER) { m_owner.Direction = EDirectionFunctions.GetDirection(gridSlot2.Position, p_party.Position); if (p_grid.MoveEntity(m_owner, lineOfSightDirection)) { m_targetSlot = gridSlot; GridSlot slot = p_grid.GetSlot(m_owner.Position); GridSlot slot2 = p_grid.GetSlot(p_party.Position); Int32 num2 = AStarHelper <GridSlot> .Calculate(slot, slot2, GameConfig.MaxSteps, m_owner, true, null); if (num2 > 0) { m_owner.DistanceToParty = num2; } else { m_owner.DistanceToParty = 99f; } m_owner.StartMovement.Trigger(); return(true); } } } } return(false); }
/// <summary> /// Generate the level /// </summary> public void Generate() { roadSize = SceneParameters.initialSize; Transform firstChunk, veryLastChunk; GameObject fline; GameObject car = GameObject.Find ("Car"); // Initialization rays = new Vector3[6]; hits = new RaycastHit[6]; bool done = false; while (!done) { RemoveAll (); lastRotY = 0.0f; lastIdx = 0; putChunks (gameObject.transform, 0.0f, 0, -1); firstChunk = transform.Find ("part-0"); AStarHelper astar = new AStarHelper (firstChunk, this); done = astar.run (); if (!done) { Debug.Log ("Trying again"); } //GameObject inicio = GameObject.CreatePrimitive(PrimitiveType.Cylinder); //inicio.transform.position= firstChunk.position ;//- new Vector3(0,0,0.25f*firstChunk.GetComponent<BoxCollider>().size.z); //Debug.Log(transform.position); } firstChunk = transform.Find ("part-0"); float carX = (firstChunk.position.x + firstChunk.GetComponent<RoadChunk> ().mountPoint.transform.position.x) / 2; float carZ = (firstChunk.position.z + firstChunk.GetComponent<RoadChunk> ().mountPoint.position.z) / 2; car.transform.position = new Vector3 (carX, firstChunk.position.y + 0.01f, carZ); car.transform.rotation = firstChunk.GetComponent<RoadChunk> ().mountPoint.rotation; car.transform.Rotate (new Vector3 (0, 180, 0)); //firstChunk.GetComponent<RoadChunk>().mountPoint.rotation.eulerAngles.y /2, 0)); //fline = UnityEngine.Object.Instantiate (FinishLine) as GameObject; //fline.transform.position = new Vector3 (1.5f, 6f, 7f); //fline.transform.rotation = new Quaternion (0, 0, 0, 0); //fline.transform.Rotate (new Vector3 (0, 90, 0)); }
// 输出的顶点数和边数相同 public bool FindCross2CrossPaths(GpsMapCell fromCross, GpsMapCell toCross, out List <MapPathGraph.NavigateVertexNode> listNavigateVertexNode, out List <MapPathGraph.Edge> listEdge, AStarHelper ash = null) { if (ash == null) { ash = new AStarHelper(this.CalcDistanceWeight); } ash.Clear(); listNavigateVertexNode = new List <MapPathGraph.NavigateVertexNode>(); listEdge = new List <MapPathGraph.Edge>(); float weight = this.pathGraph.FindShortestPaths(ash, this.pathGraph.GetVertex(fromCross.Index), this.pathGraph.GetVertex(toCross.Index), listNavigateVertexNode); this.pathGraph.NormalizeVertexAndSpotsOrder(listNavigateVertexNode, listEdge); listNavigateVertexNode.RemoveAt(0); // 去掉首结点,因其不指导导航路径,与FindCell2CrossPath一致 return(weight >= 0); }
public override void DoTurn(Grid p_grid, Party p_party) { if (m_owner.State == Monster.EState.SPAWNING) { return; } if (m_firstAction) { m_owner.AbilityHandler.ExecuteAttacks(null, null, false, EExecutionPhase.BEGIN_OF_MONSTERS_TURN); m_owner.AbilityHandler.FlushActionLog(EExecutionPhase.BEGIN_OF_MONSTERS_TURN); m_owner.BuffHandler.ModifyMonsterValues(); m_owner.CombatHandler.MeleeStrikes += m_owner.CombatHandler.MeleeStrikesRoundBonus; m_owner.CombatHandler.MeleeStrikesRoundBonus = 0; GridSlot neighborSlot = p_grid.GetSlot(m_owner.Position).GetNeighborSlot(p_grid, m_owner.Direction); if (p_grid.MoveEntity(m_owner, m_owner.Direction)) { m_targetSlot = neighborSlot; GridSlot slot = p_grid.GetSlot(m_owner.Position); GridSlot slot2 = p_grid.GetSlot(p_party.Position); Int32 num = AStarHelper <GridSlot> .Calculate(slot, slot2, GameConfig.MaxSteps, m_owner, true, null); if (num > 0) { m_owner.DistanceToParty = num; } else { m_owner.DistanceToParty = 99f; } m_owner.StartMovement.Trigger(); m_firstAction = false; return; } } else { base.DoTurn(p_grid, p_party); } }
public virtual void UpdateDistanceToParty(Party p_party, Grid p_grid) { GridSlot slot = p_grid.GetSlot(m_owner.Position); GridSlot slot2 = p_grid.GetSlot(p_party.Position); Int32 num; if (m_owner.IsAggro) { num = AStarHelper <GridSlot> .Calculate(slot, slot2, GameConfig.MaxSteps, m_owner, true, false, m_canOpenDoors, null); } else { num = AStarHelper <GridSlot> .Calculate(slot, slot2, (Int32)m_owner.AggroRange + 1, m_owner, true, false, m_canOpenDoors, null); } if (num > 0) { m_owner.DistanceToParty = num - 1; } else { m_owner.DistanceToParty = 99f; } }
// Calculate the A* path public static List <T> Calculate <T>(T start, T goal) where T : IPathNode <T> { List <T> closedset = new List <T>(); // The set of nodes already evaluated. List <T> openset = new List <T>(); // The set of tentative nodes to be evaluated. openset.Add(start); Dictionary <T, T> came_from = new Dictionary <T, T>(); // The map of navigated nodes. Dictionary <T, float> g_score = new Dictionary <T, float>(); g_score[start] = 0.0f; // Cost from start along best known path. Dictionary <T, float> h_score = new Dictionary <T, float>(); h_score[start] = HeuristicCostEstimate(start, goal); Dictionary <T, float> f_score = new Dictionary <T, float>(); f_score[start] = h_score[start]; // Estimated total cost from start to goal through y. System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); long elapsed = 0; sw.Start(); while (openset.Count != 0) { T x = LowestScore(openset, f_score); if (x.Equals(goal)) { List <T> result = new List <T>(); ReconstructPath(came_from, x, ref result); return(result); } sw.Stop(); elapsed += sw.ElapsedMilliseconds; if (elapsed > 5) { return(null); } sw.Start(); openset.Remove(x); closedset.Add(x); foreach (T y in x.Connections) { if (AStarHelper.Invalid(y) || closedset.Contains(y)) { continue; } float tentative_g_score = g_score[x] + Distance(x, y); bool tentative_is_better = false; if (!openset.Contains(y)) { openset.Add(y); tentative_is_better = true; } else if (tentative_g_score < g_score[y]) { tentative_is_better = true; } if (tentative_is_better) { came_from[y] = x; g_score[y] = tentative_g_score; h_score[y] = HeuristicCostEstimate(y, goal); f_score[y] = g_score[y] + h_score[y]; } } } return(null); }
// 输出的顶点数和边数相同 public bool FindCell2CrossPath(GpsMapCell from, GpsMapCell cross, out List <MapPathGraph.NavigateVertexNode> listNavigateVertexNode, out List <MapPathGraph.Edge> listEdge) { listNavigateVertexNode = null; listEdge = null; from = FindNearestCellOf(from, GpsMapCell.EType.EN_ROAD); if (from == null) { XxdwDebugger.Log("Road nearby not found. Strange!"); return(false); } int crossVertexIndex = this.pathGraph.FindVertex(cross.Index); if (crossVertexIndex < 0) { XxdwDebugger.Log("Target cross not found. Strange!"); return(false); } MapPathGraph.VertexNode vnTo = this.pathGraph.VertexList[crossVertexIndex]; MapPathGraph.VertexNode vn1, vn2; MapPathGraph.Edge e; int spotIndex = FindEdgeOfRoadCell(from.Index, out vn1, out vn2, out e); if (spotIndex < 0) { XxdwDebugger.Log("Cross of road not found. Strange!"); return(false); } float w1 = CalcDetailWeight(e.Spots, 0, spotIndex + 1); float w2 = CalcDetailWeight(e.Spots, spotIndex, e.Spots.Length); int[] spots1 = new int[spotIndex + 1]; Array.Copy(e.Spots, 0, spots1, 0, spotIndex + 1); int[] spots2 = new int[e.Spots.Length - spotIndex]; Array.Copy(e.Spots, spotIndex, spots2, 0, e.Spots.Length - spotIndex); MapPathGraph.Edge e1, e2; if (e.Spots[0] == vn1.Cell) { e1 = new MapPathGraph.Edge(vn1.Cell, e.Spots[spotIndex], w1, spots1, ""); e1.ReverseSpots(); e2 = new MapPathGraph.Edge(vn2.Cell, e.Spots[spotIndex], w2, spots2, ""); } else { e1 = new MapPathGraph.Edge(vn1.Cell, e.Spots[spotIndex], w2, spots2, ""); e2 = new MapPathGraph.Edge(vn2.Cell, e.Spots[spotIndex], w1, spots1, ""); e2.ReverseSpots(); } List <MapPathGraph.NavigateVertexNode> listNavigateVertexNode1 = new List <MapPathGraph.NavigateVertexNode>(); List <MapPathGraph.NavigateVertexNode> listNavigateVertexNode2 = new List <MapPathGraph.NavigateVertexNode>(); AStarHelper ash = new AStarHelper(this.CalcDistanceWeight); ash.Clear(); float weight1 = this.pathGraph.FindShortestPaths(ash, vn1, vnTo, listNavigateVertexNode1); weight1 += weight1 >= 0 ? w1 : Parameters.MAX_EDGE_WEIGHT; ash.Clear(); float weight2 = this.pathGraph.FindShortestPaths(ash, vn2, vnTo, listNavigateVertexNode2); weight2 += weight2 >= 0 ? w2 : Parameters.MAX_EDGE_WEIGHT; if (listNavigateVertexNode1.Count == 0 && listNavigateVertexNode2.Count == 0) { return(false); } listEdge = new List <MapPathGraph.Edge>(); if (weight1 < weight2) { listNavigateVertexNode1[0].SelectedEdgeIndex = this.pathGraph.GetEdgeNumber(vn1, e); listNavigateVertexNode = listNavigateVertexNode1; this.pathGraph.NormalizeVertexAndSpotsOrder(listNavigateVertexNode, listEdge); listEdge.Insert(0, e1); } else { listNavigateVertexNode2[0].SelectedEdgeIndex = this.pathGraph.GetEdgeNumber(vn2, e); listNavigateVertexNode = listNavigateVertexNode2; this.pathGraph.NormalizeVertexAndSpotsOrder(listNavigateVertexNode, listEdge); listEdge.Insert(0, e2); } return(true); }
// Calculate the A* path public static List <T> Calculate <T>(T start, T goal) where T : IPathNode <T> { List <T> closedset = new List <T>(); // The set of nodes already evaluated. List <T> openset = new List <T>(); // The set of tentative nodes to be evaluated. openset.Add(start); Dictionary <T, T> came_from = new Dictionary <T, T>(); // The map of navigated nodes. Dictionary <T, float> g_score = new Dictionary <T, float>(); g_score[start] = 0.0f; // Cost from start along best known path. Dictionary <T, float> h_score = new Dictionary <T, float>(); h_score[start] = HeuristicCostEstimate(start, goal); Dictionary <T, float> f_score = new Dictionary <T, float>(); f_score[start] = h_score[start]; // Estimated total cost from start to goal through y. while (openset.Count != 0) { T x = LowestScore(openset, f_score); if (x.Equals(goal)) { List <T> result = new List <T>(); ReconstructPath(came_from, x, ref result); return(result); } openset.Remove(x); closedset.Add(x); foreach (T y in x.Connections) { if (AStarHelper.Invalid(y) || closedset.Contains(y)) { continue; } float tentative_g_score; tentative_g_score = g_score[x] + Distance(x, y); bool tentative_is_better = false; if (!openset.Contains(y)) { openset.Add(y); tentative_is_better = true; } else if (tentative_g_score < g_score[y]) { tentative_is_better = true; } if (tentative_is_better) { came_from[y] = x; g_score[y] = tentative_g_score; h_score[y] = HeuristicCostEstimate(y, goal); f_score[y] = g_score[y] + h_score[y]; } } } Debug.Log("(movePath null, tripped in AStarHelper. IF THIS IS TRIPPED THIS IS THE REASON WHY SHIT ISN'T WORKING." + openset.Count + " " + closedset.Count); return(null); }
void FixedUpdate() { AIPlayerPathCalculationTime++; if (AIPlayerPathCalculationTime > 5 && Chase()) { //NEVER CHANGE THE FOLLOWING CODE. int layerMask = 1 << 9; //WALLS ARE LAYER LEVEL 9. THIS NUMBER CANNOT CHANGE. YOU WILL BREAK THE GAME. //NEVER CHANGE THE PREVIOUS CODE. //Check if player is in sight, no pathfinding is required if player is in sight. { Vector2 start = transform.position; Vector2 end = player.transform.position; RaycastHit2D hit = Physics2D.Linecast(start, end, layerMask); if (hit.collider != null) { playerSeen = false; } else { playerSeen = true; } } if (!playerSeen) { //TODO: LOW PRIORITY: Check if path to player already exists from closest node. If so, use said path. float distance = 999.0f; float distance2 = 999.0f; AINode closestNode = null; AINode closestNode2 = null; List <AINode> possibleNodes = new List <AINode> (); List <AINode> possiblePlayerNodes = new List <AINode> (); //MONSTER CLOSEST NODE for (int i = 0; i < World.Instance.AINodeList.Count; i++) { Vector2 start = transform.position; Vector2 end = World.Instance.AINodeList[i].transform.position; RaycastHit2D hit = Physics2D.Linecast(start, end, layerMask); if (hit.collider != null) { //This is not a possible node. continue; } else { //This is a possible node. possibleNodes.Add(World.Instance.AINodeList[i].attachedAINode); } } for (int i = 0; i < possibleNodes.Count; i++) { float tempDistance = Vector2.Distance(transform.position, possibleNodes[i].Position); if (tempDistance < distance) { distance = tempDistance; closestNode = possibleNodes[i]; } } //END MONSTER CLOSEST NODE //PLAYER CLOSEST NODE for (int i = 0; i < World.Instance.AINodeList.Count; i++) { Vector2 start = player.transform.position; Vector2 end = World.Instance.AINodeList[i].transform.position; start = Vector2.MoveTowards(start, end, 1f); RaycastHit2D hit = Physics2D.Linecast(start, end, layerMask); if (hit.collider != null) { //This is not a possible node. continue; } else { //This is a possible node. possiblePlayerNodes.Add(World.Instance.AINodeList[i].attachedAINode); } } for (int i = 0; i < possiblePlayerNodes.Count; i++) { float tempDistance = Vector2.Distance(player.transform.position, possiblePlayerNodes[i].Position); if (tempDistance < distance2) { distance2 = tempDistance; closestNode2 = possiblePlayerNodes[i]; } } Debug.DrawLine(player.transform.position, closestNode2.Position, Color.green, 0.1f); for (int i = 0; i < possiblePlayerNodes.Count; i++) { Debug.DrawLine(player.transform.position, possiblePlayerNodes[i].Position, Color.red, 0.1f); } //END PLAYER CLOSEST NODE //Calculate path. movePath = AStarHelper.Calculate(closestNode, closestNode2); //If possible node is along path, start there instead. int pathStart = 0; for (int i = 0; i < possibleNodes.Count; i++) { for (int j = 0; j < movePath.Count; j++) { if (possibleNodes[i] == movePath[j] && j > pathStart) { pathStart = j; } } } currentStep = pathStart; AIPlayerPathCalculationTime = 0; } } }
// 返回被删除的边的引用 /*private Edge RemoveEdgeNode(int vertexIndex, int adjacentIndex) * { * EdgeNode p = this.vertexList[vertexIndex].FirstEdge, q = null; * while (p != null && p.AdjacentVertex != adjacentIndex) * { * q = p; * p = p.Next; * } * * if (p != null) // 找到 * { * if (q == null) // 首条边 * { * this.vertexList[vertexIndex].FirstEdge = p.Next; * } * else * { * q.Next = p.Next; * } * * return p.EdgeLink; * } * * return null; * }*/ /// <summary> /// 采用A*算法寻最短路 /// A*算法 (F=G+H) /// 1,把起始格添加到开启列表。 /// 2,重复如下的工作: /// a) 寻找开启列表中F值最低的格子。我们称它为当前格。 /// b) 把它切换到关闭列表。 /// c) 对相邻的格中的每一个 /// * 如果它不可通过或者已经在关闭列表中,略过它。反之如下。 /// * 如果它不在开启列表中,把它添加进去。把当前格作为这一格的父节点。记录这一格的F,G,和H值。 /// * 如果它已经在开启列表中,用G值为参考检查新的路径是否更好。更低的G值意味着更好的路径。 /// * 如果是这样,就把这一格的父节点改成当前格,并且重新计算这一格的G和F值。 /// * 如果要保持的开启列表按F值排序,改变之后可能需要重新对开启列表排序。 /// d) 停止,当 /// * 把目标格添加进了关闭列表,这时候路径被找到,或者 /// * 没有找到目标格,开启列表已经空了。这时候,路径不存在。 /// 3.保存路径。从目标格开始,沿着每一格的父节点移动直到回到起始格。这就是找到的路径。 /// </summary> /// <param name="vnFrom">起点</param> /// <param name="vnTo">终点</param> /// <param name="listNavigateVertexNode">顶点表示的路径,每个元素记录的是边对应结点的入边, "并未"设置出边的序号</param> /// <returns>路径的总权值, 负数表示没找到</returns> public float FindShortestPaths(AStarHelper ash, VertexNode vnFrom, VertexNode vnTo, List <NavigateVertexNode> listNavigateVertexNode) { listNavigateVertexNode.Clear(); AStarHelper.SeekingNode me = new AStarHelper.SeekingNode(-1, 0.0f, 0.0f, null, vnFrom, null); ash.InsertIntoOpening(me); while (ash.OpeningLength > 0) { me = ash.PopLowestWeightInOpening(); VertexNode vn = me.Data as VertexNode; if (vn.Cell == vnTo.Cell) { break; // 找到 } // 遍历邻接点 EdgeNode p = vn.FirstEdge; int whichAdjacent = 0; while (p != null) { if (ash.IsInClosed(p.EdgeLink.ID)) { p = p.Next; whichAdjacent++; continue; } NavigateVertexNode nvn = new NavigateVertexNode(this.vertexList[p.AdjacentVertex] as VertexNode); nvn.SelectedEdgeIndex = whichAdjacent; nvn.SelectedEdge = p; float h = ash.hFunc(this.vertexList[p.AdjacentVertex].Cell, vnTo.Cell); //string info = string.Format("edge={0:d}<->{1:d}, g={2:f}, h={3:f}", // vn.Cell, this.vertexList[p.AdjacentVertex].Cell, me.G + p.EdgeLink.Weight, h); //XxdwDebugger.Log(info); AStarHelper.SeekingNode next = new AStarHelper.SeekingNode( p.EdgeLink.ID, me.G + p.EdgeLink.Weight, h, me, this.vertexList[p.AdjacentVertex], nvn); AStarHelper.SeekingNode pre = ash.FindInOpening(p.EdgeLink.ID); if (pre == null) { ash.InsertIntoOpening(next); } else if (next.F < pre.F) { ash.RemoveFromOpening(pre); ash.InsertIntoOpening(next); } p = p.Next; whichAdjacent++; } } // while float weight = 0.0f; if ((me.Data as VertexNode).Cell == vnTo.Cell) // 找到 { NavigateVertexNode nvn; AStarHelper.SeekingNode sn = me; while (sn != null && sn.ExtraData != null) { nvn = sn.ExtraData as NavigateVertexNode; listNavigateVertexNode.Insert(0, nvn); weight += nvn.SelectedEdge.EdgeLink.Weight; sn = sn.Parent; } listNavigateVertexNode.Insert(0, new NavigateVertexNode(vnFrom)); //加入开始节点 return(weight); } else { return(-1.0f); } }