public float CombinedDistance(CombinedPlatformAStar cpas, GameState state, GameObject next1, GameObject next2) { var combinedPath = cpas.CombinedPlatformPath (state.P1, state.P2, state.Goal, state.Goal); return Vector2.Distance (state.P1.SurfaceCenter, next1.Target) + Vector2.Distance (state.P2.SurfaceCenter, next2.Target) + WaypointHeuristic.PlatformPathDistance(combinedPath.Select(x => x.Item1), next1) + WaypointHeuristic.PlatformPathDistance(combinedPath.Select(x => x.Item2), next2); }
public List<Tuple<GameObject, GameObject>> CombinedPlatformPath( Player start1, Player start2, GameObject end1, GameObject end2) { var cacheKey = Tuple.Create (start1, start2, end1, end2); List<Tuple<GameObject, GameObject>> path; if (paths.ContainsKey(cacheKey)) { path = paths[cacheKey]; } else { // Debug.Print ("p2: {0}", start2); // Debug.Print("platsBelow 1: {0}", PlatformUtil.PlatListStr(PlatformUtil.platsBelow (Platforms, start1))); // Debug.Print("platsBelow 2: {0}", PlatformUtil.PlatListStr(PlatformUtil.platsBelow (Platforms, start2))); var platsBelow1 = PlatformUtil.platsBelow (Platforms, start1); var platsBelow2 = PlatformUtil.platsBelow (Platforms, start2); var plats1 = platsBelow1.Count () > 0 ? platsBelow1 : Platforms; var plats2 = platsBelow2.Count () > 0 ? platsBelow2 : Platforms; var startPlat1 = PlatformUtil.nearestReachablePlatform (start1, plats1); var startPlat2 = PlatformUtil.nearestReachablePlatform (start2, plats2); // Debug.Print ("startPlat1: {0}", startPlat1); // Debug.Print ("startPlat2: {0}", startPlat2); // Debug.WriteLineIf (endReachablePlatforms1.Count == 0, "No platforms within reach of the 1st goal!"); // Debug.WriteLineIf (endReachablePlatforms2.Count == 0, "No platforms within reach of the 2nd goal!"); path = runAStar (startPlat1, startPlat2, end1, end2).Select (p2g).ToList (); path.Add (Tuple.Create (end1, end2)); // Debug.Print ("ppls: {0}", PlatformUtil.PlatPairListStr (path)); paths [cacheKey] = path; } return path; }
public GameObject NextPlatform(Player player, GameObject end) { var path = PlatformPath (player, end); GameObject next; if (path.Count == 1) { next = path.First (); } else { var plat0 = path [0]; var plat1 = path [1]; var between0and1 = plat1.Distance(plat0) > plat1.Distance(player); var closeEnough = player.Distance(plat0) < (1 * Player.Size.X) && player.Y >= plat0.Y; var unreachable1 = PlatformUtil.unreachable (Platforms, player, plat1); var bothAbove = plat1.TopBoundary > player.BottomBoundary && plat0.TopBoundary > player.BottomBoundary; next = (!bothAbove && !unreachable1 && (between0and1 || closeEnough)) ? plat1 : plat0; } return next; }
public List<GameObject> PlatformPath(Player start, GameObject end) { var tup = Tuple.Create (start, end); List<GameObject> path; if (paths.ContainsKey(tup)) { path = paths[tup]; } else { var startPlat = PlatformUtil.nearestReachablePlatform (start, Platforms); var endReachablePlatforms = Platforms.FindAll (p => PlatformUtil.adjacent (Platforms, p, end)); Debug.WriteLineIf (endReachablePlatforms.Count == 0, "No platforms within reach of the goal!"); var endPlat = PlatformUtil.nearestPlatform (end.Center, endReachablePlatforms); path = runAStar (startPlat, endPlat).Concat(end).ToList<GameObject>(); paths[tup] = path; } return path; }
public Tuple<GameObject, GameObject> NextPlatform(Player player1, Player player2, GameObject end1, GameObject end2) { var path = CombinedPlatformPath (player1, player2, end1, end2); Tuple<GameObject, GameObject> next; if (path.Count == 1) { next = path.First (); } else { next = shouldGoNext(player1, path[0].Item1, path[1].Item1) || shouldGoNext(player2, path[0].Item2, path[1].Item2) ? path[1] : path[0]; } return next; }
private bool shouldGoNext(Player player, GameObject plat0, GameObject plat1) { var between0and1 = plat1.Distance(plat0) > plat1.Distance(player); var closeEnough = player.Distance(plat0) < (1 * Player.Size.X) && player.Y >= plat0.Y; var unreachable1 = PlatformUtil.unreachable (Platforms, player, plat1); var bothAbove = plat1.TopBoundary > player.BottomBoundary && plat0.TopBoundary > player.BottomBoundary; return !bothAbove && !unreachable1 && (between0and1 || closeEnough); }
private List<Tuple<Platform, Platform>> runAStar( Platform start1, Platform start2, GameObject end1, GameObject end2) { int maxIters = 200; var paths = new SortedDictionary<double, StateNode>(); var startPair = Tuple.Create (start1, start2); var root = new StateNode (null, startPair, startPair); paths.Add(combinedPlatformHeuristic(root, end1, end2), root); var best = root; for (int i = 0; i < maxIters && !(PlatformUtil.adjacent(Platforms, best.Value.Item1, end1) && PlatformUtil.adjacent(Platforms, best.Value.Item2, end2)) && paths.Count > 0; i++) { best.Children = PlatformGraph [best.Value].ToDictionary (x => x, x => new StateNode(best, x, x)); foreach (var c in best.Children) { var h = combinedPlatformHeuristic (c.Value, end1, end2); if (!paths.ContainsKey (h)) { paths.Add (h, c.Value); } } best = paths.First().Value; paths.Remove (paths.First().Key); } // foreach (var p in paths.Take(5).Reverse()) { // Debug.Print ("good path: {0}", PlatformUtil.PlatPairListStr (p.Value.ToPath().Select(tup => tup.Item2))); // } return best.ToPath().Select(tup => tup.Item2).ToList(); }
double combinedPlatformHeuristic(StateNode node, GameObject end1, GameObject end2) { var endDist1 = Vector2.Distance (node.Value.Item1.SurfaceCenter, end1.SurfaceCenter); var endDist2 = Vector2.Distance (node.Value.Item2.SurfaceCenter, end2.SurfaceCenter); var platDist = Vector2.Distance (node.Value.Item1.Center, node.Value.Item2.Center); // Arbitrary values var healthWeight = 5; var depthWeight = 30; return endDist1 + endDist2 + healthWeight * Math.Abs (HealthControl.IdealDistance - platDist) + depthWeight * node.Depth(); }
private float PlatformPathDistance(GameState state, PlayerId pId, GameObject platform) { return PlatformPathDistance (pas.PlatformPath (state.Player (pId), state.Goal), platform); }
public static float PlayerDistance(PlatformAStar pas, GameState state, PlayerId pId, GameObject target) { return Vector2.Distance (state.Player(pId).SurfaceCenter, target.Target) + PlatformPathDistance (pas.PlatformPath (state.Player (pId), state.Goal), target); }
public static float PlatformPathDistance(IEnumerable<GameObject> path, GameObject platform) { var remainingPath = path.SkipWhile(x => x != platform).ToArray(); float dist = 0f; for (int i = 0; i < remainingPath.Count () - 1; i++) { dist += remainingPath [i].Distance (remainingPath [i + 1]); } return dist; }
void DrawPlatformTargets(GameObject plat1, GameObject plat2, Color c) { }
public Point RasterizeDims(GameObject go) { return RasterizeDims(go.Size); }
public Point RasterizeCoords(GameObject go) { return RasterizeCoords (go.Coords) + new Point (0, (int)Math.Round (-yScale () * go.H)); }
public void DrawGameObjectRect(GameObject go, Color c) { Point pt = RasterizeCoords (go); Point dim = RasterizeDims (go); spriteBatch.Draw (blankTexture, new Rectangle (pt.X, pt.Y, dim.X, dim.Y), c); }
public float Distance(GameObject b) { return Vector2.Distance (SurfaceCenter, b.SurfaceCenter); }