public static void InitPaths() { savedPaths = new Dictionary<int, Dictionary<int, PathNode>>(); allNodes = new Dictionary<int, PathNode>(); foreach (WayPoint w in Main.MainObject.GameManager.GameState.Karte.WayPoints.Values) { PathNode n = new PathNode(float.MaxValue, w); allNodes.Add(w.ID, n); } }
// PathNode kopieren public PathNode Clone() { PathNode n = new PathNode(Distance, ID); if (NextNode != null) n.NextNode = NextNode.Clone(); if (PreviousNode != null) n.PreviousNode = PreviousNode.Clone(); n.WayPoint = WayPoint; n.Distance = Distance; return n; }
private static void buildPath(ref PathNode start, int targetId) { PathNode _build = allNodesTemp[targetId]; PathNode current = _build; while (current.ID != start.ID) { PathNode prev = allNodesTemp[current.PreviousNode.ID]; prev.NextNode = current; int c = current.PreviousNode.ID; current = prev; } start = allNodesTemp[start.ID]; ; }
private void searchNextVisibleNode(Enemy e) { // wenn es kein pfad gibt abbrechen if (_currentPath == null) return; PathNode temp = _currentPath.NextNode; // nodes durchgenen while (temp != null) { if (GameManager.PointSeePoint(e.LocationBehavior.Position, temp.WayPoint.Location.Position, e.LocationBehavior.Size)) { _currentPath = temp; temp = _currentPath.NextNode; } else { // aufhören zu suchen break; } } }
// Tue die Action public override void CalculateAction(Enemy e) { // ist player in sichweite if (e.DistanceLessThan(_player, e.SightiningDistance)) { // Kann er den playe sehen oder ist dieser von einem objekt bedeckt / 20x20 ist ca. ein schuss if (GameManager.PointSeePoint(e.LocationBehavior.Position, _player.LocationBehavior.Position, new Vector2(20, 20))) { // kann spieler sehen _sawPlayer = true; _sawPlayerAt = _player.LocationBehavior.Position; // wenn er in angriffreichweite ist angreifen if (e.DistanceLessThan(_player, e.SightiningDistance)) { _lookAtPlayer = true; _attack = true; _lookAtNextNode = false; _walk = false; return; } else { // Kann er zum spieler laufen ohne an eine wand zu stoßen? if (GameManager.PointSeePoint(e.LocationBehavior.Position, _player.LocationBehavior.Position, e.LocationBehavior.Size)) { _lookAtPlayer = true; _attack = false; _lookAtNextNode = false; _walk = true; return; } } } } else { _lookAtPlayer = false; _attack = false; } // ## Sieht er den player und kann schießen wird abgebrochen // wenn er den spiele sehen konnte aber jetzt nicht mehr if (_sawPlayer) { // sieht player nicht mehr _sawPlayer = false; // Suche den nähsten WP und schaue ob er auf der route lag WayPoint _newNearest = Karte.SearchNearest(_sawPlayerAt); if (_newNearest != null) { // nearest in path PathNode nearestInPath = null; // wenn der nähste wegpunkt im pfad ist, diesen als neues ziel setzten if (_currentPath.IsWaypointInPath(_newNearest.ID, out nearestInPath)) { _currentPath = nearestInPath; } else { // ansonsten den aktuellen pfad löschen und neuen berechnen _nearest = _newNearest; _currentPath = null; } } } // // WP des Players WayPoint playerWayPoint = Main.MainObject.GameManager.GameState.Player.NearestWayPoint; // falls playerwegpunkt neu ist pfad neu berechnen und auch neuen nearest suchen if (playerWayPoint != null && _lastPlayerWaypoint != playerWayPoint) { _nearest = null; _currentPath = null; } // Falls es kein Wegpunkt gibt, der am nähesten bei mir ist if (_nearest == null) _nearest = Karte.SearchNearest(e.LocationBehavior.Position); // Sollte es kein Wegpunkt in meiner Nähe geben abbrechen if (_nearest == null) return; // wenn es kein pfad gigt, pfad zu player berechnen if (_currentPath == null && playerWayPoint != null) { _lastPlayerWaypoint = playerWayPoint; _currentPath = PathFinder.FindePath(_nearest, playerWayPoint); } // wenn _currentPath == null stehen bleiben ) if (_currentPath != null) { // Steht enemy über wp => next wp if (Vector2.Distance(_currentPath.WayPoint.Location.Position, e.LocationBehavior.Position) < 10) { // wenn es einen nächste wp gibt gehe zu dem ansonsten laufen=false /stehen bleiben if (_currentPath.NextNode == null) { _lookAtPlayer = false; _attack = false; _lookAtNextNode = false; _walk = false; } else { _currentPath = _currentPath.NextNode; _lookAtPlayer = false; _attack = false; _lookAtNextNode = true; _walk = true; } } else { // checken ob enemy festhängt - hängt fest wenn er halb so schnell wie normal läuft if (_walkedDistance < e.Speed / 2) { searchNextVisibleNode(e); } _lookAtPlayer = false; _attack = false; _lookAtNextNode = true; _walk = true; } } else { _lookAtPlayer = false; _attack = false; _lookAtNextNode = false; _walk = false; } }
private static PathNode _findePath(WayPoint start, WayPoint target) { // Listen init openList = new List<PathNode>(); closedList = new List<PathNode>(); allNodesTemp = CloneNodeDic(); // Start einfügen PathNode startNode = new PathNode(0, start); openList.Add(startNode); // solange openlist nicht leer ist while (openList.Count > 0) { //next Node aus openlist holen PathNode next = openList[0]; openList.RemoveAt(0); // Nachbarn einfügen expandNode(next); // Node in closeliste einfügn closedList.Add(next); // prüfen ob ich schon fertig bin if (next.ID == target.ID) break; } // pfad bauen buildPath(ref startNode, target.ID); return startNode; }
private static void expandNode(PathNode n) { foreach (WayPoint w in n.WayPoint.connectedPoints) { // Pathnode mit distanz erzeugen PathNode node = allNodesTemp[w.ID]; // node adden falls er noch nicht in openlist und closelist ist if (closedList.Contains(node)) continue; // distanz zu nachbar float dist = n.Distance + n.WayPoint.distances[w.ID]; // checken ob er schon in openlist ist if (openList.Contains(node)) { // Distanz und vorgänger udpaten falls distanz kleiner ist if (dist < node.Distance) { node.Distance = dist; node.PreviousNode = n; } } else { // vorgänger setzten node.PreviousNode = n; node.Distance = dist; // pathnode in open list openList.Add(node); } } // List sortieren openList.Sort(CompareNodes); }
/*private static PathNode _findePath(WayPoint start, WayPoint target) { //Debug.WriteLine("pfad berechnen von " + start.ID + " zu " + target.ID); if (start == target) { if (!savedPaths.ContainsKey(start.ID)) savedPaths.Add(start.ID, new Dictionary<int, PathNode>()); // Pfad clonen und speichern savedPaths[start.ID].Add(target.ID, new PathNode(0, start.ID)); return new PathNode(0, start.ID); } // Listen initialisieren openList = new List<PathNode>(); closedList = new List<PathNode>(); // Startpunkt in die openList machen PathNode startNode = new PathNode(0, start.ID); openList.Add(startNode); // Gefundener Pfad PathNode found = null; // Solange openlist nicht leer ist while (openList.Count > 0) { // Erster Knoten aus der openlist holen und entfernen (kürzester weg zum ziel) PathNode current = openList[0]; openList.Remove(current); // Falls current == ziel beenden if (current.ID == target.ID) { found = current; break; } // Kinder in open list einfügen expandNode(current); // aktuelle knoten in closed list einfügen closedList.Add(current); } // Pfad umdrehen if (found != null) { PathNode reverse = null; PathNode reverseCurrent = null; while (found.PreviousNode != null) { // Letzte Knoten holen PathNode last = popLastNode(found); // Letzte knoten an neue liste hängen if (reverse == null) { reverse = last; reverseCurrent = reverse; } else { reverseCurrent.NextNode = last; reverseCurrent = reverseCurrent.NextNode; } } // Letztes Element noch anhängen reverseCurrent.NextNode = found; // Pfad speichern um ihn nicht erneut berechnen zu müssen if (!savedPaths.ContainsKey(start.ID)) savedPaths.Add(start.ID, new Dictionary<int, PathNode>()); // Pfad clonen und speichern savedPaths[start.ID].Add(target.ID, reverse.Clone()); // Pfad zurückgeben return reverse; } // Pfad zurückgeben return found; } // *************************************************************** // holt den letzten node aus dem pfad private static PathNode popLastNode(PathNode n) { while (n.PreviousNode.PreviousNode != null) { n = n.PreviousNode; } PathNode prev = n.PreviousNode; n.PreviousNode = null; return prev; } // *************************************************************** // openlist etc updaten private static void expandNode(PathNode current) { WayPoint currentWayPoint = Main.MainObject.GameManager.GameState.Karte.WayPoints[current.ID]; // Alle verlinkten knoten durchgehen foreach (WayPoint w in currentWayPoint.connectedPoints) { // falls der knoten in der closed list ist nicht unternehmen if (isIdInClosedList(w.ID)) continue; // weg zwischen current und neuen knoten float dX = currentWayPoint.Location.Position.X - w.Location.Position.X; float dY = currentWayPoint.Location.Position.Y - w.Location.Position.Y; float dist = (float)Math.Sqrt(Math.Pow(dX, 2) + Math.Pow(dY, 2)); // neuer knoten erstellen PathNode newNode = new PathNode(current.Distance + dist, w.ID); newNode.PreviousNode = current; // In openlist schauen ob es den punkt schon gibt und prüfen ob er schneller zu erreichen ist PathNode nexter = GetOfOpenList(w.ID); if (nexter != null) { // wenn der alte weg kürzer ist weiter machen if (nexter.Distance < newNode.Distance) continue; else { // wenn der neue weg kürzer ist, node aktuallisiern nexter.Distance = newNode.Distance; nexter.PreviousNode = current; } } else { // knoten in open list adden openList.Add(newNode); } } // list sortieren, damit oben der mit der kürzesten heuristik steht openList.Sort(CompareNodes); } private static bool isIdInClosedList(int id) { foreach (PathNode n in closedList) if (n.ID == id) return true; return false; } private static PathNode GetOfOpenList(int id) { foreach (PathNode n in closedList) if (n.ID == id) return n; return null; }*/ // ************************************************************************** // Vergleicht zwei PathNodes private static int CompareNodes(PathNode x, PathNode y) { if (x == null) { if (y == null) { // equal return 0; } else { // y ist nicht null somit ist y "größer" return -1; } } else { // x nicht null if (y == null) // und y ist null ist x "größer" { return 1; } else { // ansonsten vergleichen if (x.Distance > y.Distance) { return 1; } else if (x.Distance < y.Distance) { return -1; } else { return 0; } } } }
// ************************************************************************** // Prüft ob sich in einem pfad ein bestimmter wegpunkt befindet public bool IsWaypointInPath(int waypointId, out PathNode outNode) { PathNode current = this; while (current != null) { if (current.ID == waypointId) { outNode = current; return true; } current = current.NextNode; } outNode = null; return false; }