public List <Node> FindPath(Node start, Node end) { PriorityQueue <float, Node> S = new PriorityQueue <float, Node>(); Dictionary <Node, Node> previous = new Dictionary <Node, Node>(); Dictionary <Node, float> distance = new Dictionary <Node, float>(); S.Enqueue(0, start); previous.Add(start, null); distance.Add(start, 0); while (!S.IsEmpty) { Node n = S.Dequeue(); if (n == end) { List <Node> path = new List <Node>(); path.Add(n); while ((n = previous[n]) != null) { path.Add(n); } return(path); } foreach (Edge e in n.Edges.Values) { Node neighbour = e.Left; if (neighbour == n) { neighbour = e.Right; } if (!previous.ContainsKey(neighbour)) { float dist = distance[n] + e.Distance; float distLeft = (neighbour.Center - end.Center).Length(); float h = dist + distLeft; S.Enqueue(h, neighbour); previous.Add(neighbour, n); distance.Add(neighbour, dist); } } } return(null); }
public List <Waypoint> FindPath(Vector3 start, Vector3 end, Node startNode, Node endNode) { Node s = startNode ?? BoundingRegion.GetNodeAt(start); Node e = endNode ?? BoundingRegion.GetNodeAt(end); if (s == null || e == null || s == e) { return(null); } List <Node> nodePath = FindPath(s, e); if (nodePath == null) { return(null); } List <Waypoint> allWaypoints = new List <Waypoint>(); allWaypoints.Add(new Waypoint { InternalIndex = allWaypoints.Count, OptimalPoint = end, Node = e, Edge = null //nodePath[0].Edges[nodePath[1]] }); for (int i = 0; i < nodePath.Count - 1; i++) { Edge ed = nodePath[i].Edges[nodePath[i + 1]]; allWaypoints.Add(new Waypoint { InternalIndex = allWaypoints.Count, OptimalPoint = (ed.PointA + ed.PointB) / 2, Node = nodePath[i + 1], Edge = ed }); } allWaypoints.Add(new Waypoint { InternalIndex = allWaypoints.Count, OptimalPoint = start, Node = s, Edge = null //nodePath[nodePath.Count - 2].Edges[nodePath[nodePath.Count - 1]] }); bool[] disabled = new bool[allWaypoints.Count]; for (int i = 0; i < disabled.Length; i++) { disabled[i] = false; } // The first iteration removes unneccessary waypoints // Go through, waypoint by waypoint for (int left = 0; left < allWaypoints.Count - 2; left++) { //And see if we can remove any succeding waypoints for this one for (int right = left + 2; right < allWaypoints.Count; right++) { if (CanMoveStraight(allWaypoints, left, right, allWaypoints[left].OptimalPoint, Vector3.Normalize(allWaypoints[right].OptimalPoint - allWaypoints[left].OptimalPoint))) { disabled[right - 1] = true; } else { left = right - 2; break; } } } List <Waypoint> waypoints = new List <Waypoint>(); for (int i = 0; i < allWaypoints.Count; i++) { if (!disabled[i]) { waypoints.Add(allWaypoints[i]); } } //This tries to move the waypoints along the edge they occupy to optimize the path, //basically cutting corners //Problem is, it actually looks a bit better if the units walk in the middle of the path //instead of taking the absolutely best path, so it's turned off #if (false) for (int i = 1; i < waypoints.Count - 1; i++) { Edge ed = waypoints[i].Edge; //We start by finding the intersection point of the current optimal point float currentT = (waypoints[i].OptimalPoint - ed.PointA).Length(); //And of the best point (a line from the previous waypoint to the next one float bestT; if (Math.LineLineIntersectionTA(ed.PointA, Vector3.Normalize(ed.PointB - ed.PointA), waypoints[i - 1].OptimalPoint, Vector3.Normalize(waypoints[i + 1].OptimalPoint - waypoints[i - 1].OptimalPoint), out bestT)) { //From that we know which "corner" is the best place for the optimal point Vector3 WP; if (bestT < currentT) { WP = ed.PointA; } else if (bestT > currentT) { WP = ed.PointB; } else { continue; } //Then we just need to check if it's ok to place it there if (CanMoveStraight(allWaypoints, waypoints[i - 1].InternalIndex, waypoints[i].InternalIndex, waypoints[i - 1].OptimalPoint, Vector3.Normalize(WP - waypoints[i - 1].OptimalPoint)) && CanMoveStraight(allWaypoints, waypoints[i].InternalIndex, waypoints[i + 1].InternalIndex, WP, Vector3.Normalize(waypoints[i + 1].OptimalPoint - WP))) { waypoints[i].OptimalPoint = WP; } } else { /*if (CanMoveStraight(nodePath, waypointNodeIndexes[i - 2], waypointNodeIndexes[i - 1] - 1, * waypoints[i - 2].OptimalPoint, Vector3.Normalize(waypoints[i - 1].OptimalPoint - waypoints[i - 2].OptimalPoint))) * waypoints[i].OptimalPoint = waypoints[i - 1].OptimalPoint;*/ } } #endif List <Waypoint> revWP = new List <Waypoint>(); revWP.Add(waypoints.Last()); for (int i = waypoints.Count - 2; i >= 0; i--) { if (waypoints[i] != revWP.Last()) { revWP.Add(waypoints[i]); } } return(revWP); }
void SpawnOneUnit() { #if DEBUG RedGate.Profiler.UserEvents.ProfilerEvent.SignalEvent("Spawning unit"); #endif Vector3 spawnPos; if (region != null) { if (Distribution == SpawnDistribution.Even) { node = region.BoundingRegion.Nodes[nodeI]; nodeI++; if (nodeI >= region.BoundingRegion.Nodes.Length) nodeI = 0; } if (Distribution == SpawnDistribution.GroupRandom || Distribution == SpawnDistribution.Even) spawnPos = region.BoundingRegion.GetRandomPosition(Game.Instance.SpawnRandomizer, node); else spawnPos = region.BoundingRegion.GetRandomPosition(Game.Instance.SpawnRandomizer); spawnPos += PointOffset; } else if (point is GameEntity) { spawnPos = ((GameEntity)point).SpawnAtPoint; spawnPos += Vector3.TransformCoordinate(PointOffset, Matrix.RotationZ(((GameEntity)point).Orientation)); } else { spawnPos = point.Translation + Vector3.UnitZ * 0.1f; spawnPos += Vector3.TransformCoordinate(PointOffset, Matrix.RotationQuaternion(point.Rotation)); } spawnPos = Game.Instance.Map.Ground.GetHeight(spawnPos); var type = binder.BindToType(typeof(SpawnScript).Assembly.FullName, SpawnType); /*var type = typeof(SpawnScript).Assembly.GetType("Client.Game.Map.Units." + SpawnType); if(type == null) typeof(SpawnScript).Assembly.GetType("Client.Game.Map.Props." + SpawnType);*/ var unit = (GameEntity)Activator.CreateInstance(type); unit.Translation = spawnPos; unit.EditorInit(); unit.GameStart(); Game.Instance.Scene.Root.AddChild(unit); if (DisableUnit) { ((Unit)unit).CanControlMovementBlockers++; ((Unit)unit).CanControlRotationBlockers++; ((Unit)unit).CanPerformAbilitiesBlockers++; } if (unit is NPC && SeekMainCharacter && Game.Instance.Map.MainCharacter.State == UnitState.Alive) ((NPC)unit).MotionNPC.Pursue(Game.Instance.Map.MainCharacter.MotionObject, 0); if (SpawnEffect != null) { var e = (Graphics.Entity)Activator.CreateInstance(SpawnEffect); e.Translation = spawnPos; Game.Instance.Scene.Add(e); } if (LimitSimultaneouslyAlive > 0 && unit is Destructible) spawns.Add((Destructible)unit); }
protected override void PerformingTick() { base.PerformingTick(); for (int i = 0; i < frameSpawnN; i++) SpawnOneUnit(); frameSpawnN = 0; if (!(SkipFirstTick && isFirstTick)) { if (point == null && region == null) { region = Game.Instance.Map.GetRegion(Point); if (region == null) point = Game.Instance.Scene.GetByName(Point); } if (region != null && Distribution == SpawnDistribution.GroupRandom) { if (Distribution == SpawnDistribution.GroupRandom) node = region.BoundingRegion.GetRandomNode(Game.Instance.SpawnRandomizer); else nodeI = 0; } int n = SpawnMinPerRound + Game.Instance.SpawnRandomizer.Next(SpawnMaxPerRound - SpawnMinPerRound); n = Math.Min(n, SpawnCount - spawnedCount); if (LimitSimultaneouslyAlive > 0) { List<Destructible> alive= new List<Destructible>(); foreach (var v in spawns) if (v.State == UnitState.Alive) alive.Add(v); spawns = alive; n = Common.Math.Clamp(n, 0, Math.Max(0, LimitSimultaneouslyAlive - alive.Count)); } spawnedCount += n; frameSpawnN = n; if (n == 0 && EndPerformWhenAllUnitsHaveSpawned) TryEndPerform(false); } isFirstTick = false; TickPeriod = MinPeriod + (float)Game.Instance.SpawnRandomizer.NextDouble() * (MaxPeriod - MinPeriod); }
public List<Waypoint> FindPath(Vector3 start, Vector3 end, Node startNode, Node endNode) { Node s = startNode ?? BoundingRegion.GetNodeAt(start); Node e = endNode ?? BoundingRegion.GetNodeAt(end); if (s == null || e == null || s == e) return null; List<Node> nodePath = FindPath(s, e); if (nodePath == null) return null; List<Waypoint> allWaypoints = new List<Waypoint>(); allWaypoints.Add(new Waypoint { InternalIndex = allWaypoints.Count, OptimalPoint = end, Node = e, Edge = null //nodePath[0].Edges[nodePath[1]] }); for(int i=0; i < nodePath.Count - 1; i++) { Edge ed = nodePath[i].Edges[nodePath[i + 1]]; allWaypoints.Add(new Waypoint { InternalIndex = allWaypoints.Count, OptimalPoint = (ed.PointA + ed.PointB) / 2, Node = nodePath[i + 1], Edge = ed }); } allWaypoints.Add(new Waypoint { InternalIndex = allWaypoints.Count, OptimalPoint = start, Node = s, Edge = null //nodePath[nodePath.Count - 2].Edges[nodePath[nodePath.Count - 1]] }); bool[] disabled = new bool[allWaypoints.Count]; for (int i = 0; i < disabled.Length; i++) disabled[i] = false; // The first iteration removes unneccessary waypoints // Go through, waypoint by waypoint for (int left = 0; left < allWaypoints.Count - 2; left++) { //And see if we can remove any succeding waypoints for this one for (int right = left + 2; right < allWaypoints.Count; right++) { if (CanMoveStraight(allWaypoints, left, right, allWaypoints[left].OptimalPoint, Vector3.Normalize(allWaypoints[right].OptimalPoint - allWaypoints[left].OptimalPoint))) disabled[right - 1] = true; else { left = right - 2; break; } } } List<Waypoint> waypoints = new List<Waypoint>(); for(int i=0; i < allWaypoints.Count; i++) if (!disabled[i]) waypoints.Add(allWaypoints[i]); //This tries to move the waypoints along the edge they occupy to optimize the path, //basically cutting corners //Problem is, it actually looks a bit better if the units walk in the middle of the path //instead of taking the absolutely best path, so it's turned off #if(false) for (int i = 1; i < waypoints.Count - 1; i++) { Edge ed = waypoints[i].Edge; //We start by finding the intersection point of the current optimal point float currentT = (waypoints[i].OptimalPoint - ed.PointA).Length(); //And of the best point (a line from the previous waypoint to the next one float bestT; if (Math.LineLineIntersectionTA(ed.PointA, Vector3.Normalize(ed.PointB - ed.PointA), waypoints[i - 1].OptimalPoint, Vector3.Normalize(waypoints[i + 1].OptimalPoint - waypoints[i - 1].OptimalPoint), out bestT)) { //From that we know which "corner" is the best place for the optimal point Vector3 WP; if (bestT < currentT) WP = ed.PointA; else if (bestT > currentT) WP = ed.PointB; else continue; //Then we just need to check if it's ok to place it there if (CanMoveStraight(allWaypoints, waypoints[i - 1].InternalIndex, waypoints[i].InternalIndex, waypoints[i - 1].OptimalPoint, Vector3.Normalize(WP - waypoints[i - 1].OptimalPoint)) && CanMoveStraight(allWaypoints, waypoints[i].InternalIndex, waypoints[i + 1].InternalIndex, WP, Vector3.Normalize(waypoints[i + 1].OptimalPoint - WP))) waypoints[i].OptimalPoint = WP; } else { /*if (CanMoveStraight(nodePath, waypointNodeIndexes[i - 2], waypointNodeIndexes[i - 1] - 1, waypoints[i - 2].OptimalPoint, Vector3.Normalize(waypoints[i - 1].OptimalPoint - waypoints[i - 2].OptimalPoint))) waypoints[i].OptimalPoint = waypoints[i - 1].OptimalPoint;*/ } } #endif List<Waypoint> revWP = new List<Waypoint>(); revWP.Add(waypoints.Last()); for (int i = waypoints.Count - 2; i >= 0; i--) if (waypoints[i] != revWP.Last()) revWP.Add(waypoints[i]); return revWP; }
public List<Node> FindPath(Node start, Node end) { PriorityQueue<float, Node> S = new PriorityQueue<float, Node>(); Dictionary<Node, Node> previous = new Dictionary<Node, Node>(); Dictionary<Node, float> distance = new Dictionary<Node, float>(); S.Enqueue(0, start); previous.Add(start, null); distance.Add(start, 0); while (!S.IsEmpty) { Node n = S.Dequeue(); if (n == end) { List<Node> path = new List<Node>(); path.Add(n); while ((n = previous[n]) != null) path.Add(n); return path; } foreach (Edge e in n.Edges.Values) { Node neighbour = e.Left; if (neighbour == n) neighbour = e.Right; if (!previous.ContainsKey(neighbour)) { float dist = distance[n] + e.Distance; float distLeft = (neighbour.Center - end.Center).Length(); float h = dist + distLeft; S.Enqueue(h, neighbour); previous.Add(neighbour, n); distance.Add(neighbour, dist); } } } return null; }