private PathWaypoint generateIdlePath(SortedVector2List <Platform> platforms, CollidableObj obj, AI ai, int jumpStrength, int xVelocity, float gravity, PathWaypoint curWapoint = null) { ConnectivityNode curNode = null; if (curWapoint != null && !(connectivityGraph.ContainsKey((int)curWapoint.position.X) && connectivityGraph[(int)curWapoint.position.X].ContainsKey((int)curWapoint.position.Y))) { curWapoint = null; } if (curWapoint != null) { curNode = connectivityGraph[(int)curWapoint.position.X][(int)curWapoint.position.Y]; } if (curNode == null) { List <Vector2> res = getClosestNodeKeyForPosition(platforms, obj, obj.Position, obj.Position, gravity, xVelocity, jumpStrength); if (res == null) { return(null); } foreach (Vector2 v in res) { if (ai.inBoundingBox(v)) { return(new PathWaypoint(v, null, PathType.Free)); } } } List <PathWaypoint> waypoints = new List <PathWaypoint> { new PathWaypoint(new Vector2(obj.Position.X, obj.getBot()), null, PathType.Free) }; if (curNode != null) { foreach (ConnectivityPath path in curNode.connections) { if (ai.inBoundingBox(path.endNode.position)) { bool jumpPath = path.jumpPath && path.jumpableStrengths[jumpStrength] && path.minXVel(jumpStrength, 0.15f) <= xVelocity; bool straightPath = path.straightPath && path.minXVel(0, 0.15f) <= xVelocity; if (straightPath) { waypoints.Add(new PathWaypoint(path.endNode.position, null, PathType.Straight)); } if (jumpPath) { waypoints.Add(new PathWaypoint(path.endNode.position, null, PathType.Jump)); } } } } return(waypoints[new Random().Next(waypoints.Count)]); }
private List <Vector2> getClosestNodeKeyForPosition(SortedVector2List <Platform> platforms, CollidableObj obj, Vector2 pos, Vector2 goal, float gravity, int xVelocity, int?jumpStrength = null) { if (connectivityGraph.Count == 0) { return(null); } int maxSearchRange = MAX_NODE_SEARCH_RANGE; if (jumpStrength != null) { maxSearchRange = (int)(Math.Pow((int)jumpStrength, 2) / gravity) / 2; } Vector2 ret = new Vector2(0, 1); int begin = 0; int end = connectivityGraph.Count; while (!(pos.X <= connectivityGraph.Keys[begin + (end - begin) / 2] && pos.X >= connectivityGraph.Keys[begin + (end - begin) / 2 - 1] || pos.X >= connectivityGraph.Keys[begin + (end - begin) / 2] && pos.X <= connectivityGraph.Keys[begin + (end - begin) / 2 + 1])) { if (pos.X > connectivityGraph.Keys[begin + (end - begin) / 2]) { begin = begin + (end - begin) / 2 + 1; } else { end = begin + (end - begin) / 2; } } int i; if (pos.X < connectivityGraph.Keys[begin + (end - begin) / 2]) { if (Math.Abs(pos.X - connectivityGraph.Keys[begin + (end - begin) / 2]) < Math.Abs(pos.X - connectivityGraph.Keys[begin + (end - begin) / 2 - 1])) { i = begin + (end - begin) / 2; } else { i = begin + (end - begin) / 2 - 1; } } else if (Math.Abs(pos.X - connectivityGraph.Keys[begin + (end - begin) / 2]) < Math.Abs(pos.X - connectivityGraph.Keys[begin + (end - begin) / 2 + 1])) { i = begin + (end - begin) / 2; } else { i = begin + (end - begin) / 2 + 1; } ret.X = connectivityGraph.Keys[i]; int prevXIndex = i - 1; int postXIndex = i + 1; int lowXBound = (int)(pos.X - Math.Sqrt(maxSearchRange * 2 / gravity) * xVelocity); int highXBound = (int)(pos.X + Math.Sqrt(maxSearchRange * 2 / gravity) * xVelocity); MinHeap <Tuple <float, Vector2> > bestNodes = new MinHeap <Tuple <float, Vector2> >(delegate(Tuple <float, Vector2> n1, Tuple <float, Vector2> n2) { if (n1.Item1 < n2.Item1) { return(-1); } else if (n1.Item1 == n2.Item1) { return(0); } else { return(1); } }); while (true) { begin = 0; end = connectivityGraph[(int)ret.X].Count; if ((end == 1 || end == 2) && obj.getBot(pos) <= connectivityGraph[(int)ret.X].Keys[0]) { ret.Y = connectivityGraph[(int)ret.X].Keys[0]; } else if (end == 2 && obj.getBot(pos) <= connectivityGraph[(int)ret.X].Keys[1]) { ret.Y = connectivityGraph[(int)ret.X].Keys[1]; } else { while (begin + (end - begin) / 2 != 0 && begin + (end - begin) / 2 + 1 != connectivityGraph[(int)ret.X].Count && !(obj.getBot(pos) <= connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2] && obj.getBot(pos) >= connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2 - 1] || obj.getBot(pos) >= connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2] && obj.getBot(pos) <= connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2 + 1])) { if (obj.getBot(pos) > connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2]) { begin = begin + (end - begin) / 2 + 1; } else { end = begin + (end - begin) / 2; } } if (begin + (end - begin) / 2 + 1 != connectivityGraph[(int)ret.X].Count) { if (obj.getBot(pos) < connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2]) { ret.Y = connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2]; } else { ret.Y = connectivityGraph[(int)ret.X].Keys[begin + (end - begin) / 2 + 1]; } } } if (ret.Y != 1 && straightable(platforms, new Vector2(pos.X, obj.getBot(pos)), ret) && straightable(platforms, new Vector2(obj.getLeft(pos), pos.Y), new Vector2(obj.getLeft(pos), ret.Y + (pos.Y - obj.getBot(pos)))) && straightable(platforms, new Vector2(obj.getRight(pos), pos.Y), new Vector2(obj.getRight(pos), ret.Y + (pos.Y - obj.getBot(pos)))) && straightable(platforms, new Vector2(pos.X, obj.getTop(pos)), new Vector2(ret.X, ret.Y + (obj.getTop(pos) - obj.getBot(pos)))) && (obj.getBot(pos) == ret.Y && (straightable(platforms, new Vector2(obj.getLeft(pos), obj.getBot(pos)), ret, true) || straightable(platforms, new Vector2(obj.getRight(pos), obj.getBot(pos)), ret, true)) || Math.Sqrt(Math.Abs(obj.getBot(pos) - ret.Y) * 2 / gravity) * xVelocity > Math.Abs(pos.X - ret.X) && Math.Abs(obj.getBot(pos) - ret.Y) < maxSearchRange)) { bestNodes.add(new Tuple <float, Vector2>((float)Math.Sqrt(Math.Abs(pos.X - ret.Y) * 2 / gravity) + distance(ret, goal), ret)); } ret.Y = 1; if (prevXIndex == -1 && (postXIndex == connectivityGraph.Keys.Count || connectivityGraph.Keys[postXIndex] > highXBound) || prevXIndex != -1 && connectivityGraph.Keys[prevXIndex] < lowXBound && (postXIndex == connectivityGraph.Keys.Count || connectivityGraph.Keys[postXIndex] > highXBound)) { if (!bestNodes.empty()) { List <Vector2> retList = new List <Vector2>(); while (!bestNodes.empty()) { retList.Add(bestNodes.peek().Item2); bestNodes.pop(); } return(retList); } else { return(null); } } if (prevXIndex == -1 || connectivityGraph.Keys[prevXIndex] < lowXBound) { ret.X = connectivityGraph.Keys[postXIndex++]; } else if (postXIndex == connectivityGraph.Keys.Count || connectivityGraph.Keys[postXIndex] > highXBound) { ret.X = connectivityGraph.Keys[prevXIndex--]; } else if (Math.Abs(pos.X - connectivityGraph.Keys[prevXIndex]) < Math.Abs(pos.X - connectivityGraph.Keys[postXIndex])) { ret.X = connectivityGraph.Keys[prevXIndex--]; } else { ret.X = connectivityGraph.Keys[postXIndex++]; } } }
private PathWaypoint getPath(SortedVector2List <Platform> platforms, CollidableObj start, CollidableObj end, int jumpStrength, int xVelocity, float gravity, PathWaypoint curWapoint = null) { Dictionary <Vector2, ConnectivityNodeWrapper> exploredSet = new Dictionary <Vector2, ConnectivityNodeWrapper>(); Dictionary <Vector2, ConnectivityNodeWrapper> openSet = new Dictionary <Vector2, ConnectivityNodeWrapper>(); MinHeap <ConnectivityNodeWrapper> queue = new MinHeap <ConnectivityNodeWrapper>(delegate(ConnectivityNodeWrapper n1, ConnectivityNodeWrapper n2) { if (n1.heurisitc < n2.heurisitc) { return(-1); } else if (n1.heurisitc == n2.heurisitc) { return(0); } else { return(1); } }); List <Vector2> res; ConnectivityNodeWrapper curNode; if (curWapoint != null && !(connectivityGraph.ContainsKey((int)curWapoint.position.X) && connectivityGraph[(int)curWapoint.position.X].ContainsKey((int)curWapoint.position.Y))) { curWapoint = null; } if (curWapoint != null) { curNode = new ConnectivityNodeWrapper(connectivityGraph[(int)curWapoint.position.X][(int)curWapoint.position.Y], calculateHeuristic(curWapoint.position, end.Position, xVelocity, jumpStrength)); } else { res = getClosestNodeKeyForPosition(platforms, start, start.Position, end.Position, gravity, xVelocity); if (res == null) { return(null); } foreach (Vector2 vec in res) { ConnectivityNodeWrapper cnw = new ConnectivityNodeWrapper(connectivityGraph[(int)vec.X][(int)vec.Y], calculateHeuristic(vec, end.Position, xVelocity, jumpStrength)); queue.add(cnw); openSet.Add(cnw.node.position, cnw); } curNode = queue.peek(); queue.pop(); openSet.Remove(curNode.node.position); } res = getClosestNodeKeyForPosition(platforms, end, end.Position, end.Position, gravity, xVelocity, jumpStrength); if (res == null) { return(null); } ConnectivityNode endNode = connectivityGraph[(int)res[0].X][(int)res[0].Y]; int it = 0; while (curNode != endNode) { foreach (ConnectivityPath path in curNode.node.connections) { if (!exploredSet.ContainsKey(path.endNode.position)) { bool jumpPath = path.jumpPath && path.jumpableStrengths[jumpStrength] && path.minXVel(jumpStrength, gravity) <= xVelocity; bool straightPath = path.straightPath && (path.minXVel(0, gravity) <= xVelocity || path.walkable); if (straightPath) { float h = calculateHeuristic(path.endNode.position, endNode.position, xVelocity, jumpStrength); if (!openSet.ContainsKey(path.endNode.position)) { ConnectivityNodeWrapper cnw = new ConnectivityNodeWrapper(path.endNode, path.getStraightPathCost(xVelocity, gravity), h, curNode, PathType.Straight); queue.add(cnw); openSet.Add(cnw.node.position, cnw); } else if (openSet[path.endNode.position].heurisitc > h) { ConnectivityNodeWrapper cnw = new ConnectivityNodeWrapper(path.endNode, path.getStraightPathCost(xVelocity, gravity), h, curNode, PathType.Straight); queue.add(cnw); openSet[path.endNode.position] = cnw; } } else if (jumpPath) { queue.add(new ConnectivityNodeWrapper(path.endNode, path.jumpCosts[jumpStrength], calculateHeuristic(path.endNode.position, endNode.position, xVelocity, jumpStrength), curNode, PathType.Jump)); } } } exploredSet.Add(curNode.node.position, curNode); ++it; if (it == 20) { return(null); } do { if (queue.empty()) { return(null); } curNode = queue.peek(); queue.pop(); } while (exploredSet.ContainsKey(curNode.node.position)); } PathWaypoint pathWaypoint = new PathWaypoint(new Vector2(end.Position.X, end.getBot()), null, PathType.Free); while (curNode != (object)null) { pathWaypoint = new PathWaypoint(curNode.node.position, pathWaypoint, curNode.pathType); curNode = curNode.parent; } if (curWapoint != null) { pathWaypoint = pathWaypoint.nextWaypoint; } return(pathWaypoint); }