private double[] getObjectMinMax(Vector2 axis, CollidableObj obj, float timeDisplacement = 0, bool useVelocity = false) { double[] ret = new double[2]; for (int i = 0; i < obj.collisionArea.Count; ++i) { Vector2 p = obj.collisionArea[i] * new Vector2((int)obj.direction, 1) + obj.Position + (useVelocity ? obj.Velocity * timeDisplacement : new Vector2(0, 0)); if (i == 0) { ret[0] = axis.X * p.X + axis.Y * p.Y; ret[1] = ret[0]; } else { double curPointAxisMagnitude = axis.X * p.X + axis.Y * p.Y; if (curPointAxisMagnitude < ret[0]) { ret[0] = curPointAxisMagnitude; } else if (curPointAxisMagnitude > ret[1]) { ret[1] = curPointAxisMagnitude; } } } return(ret); }
public void collide(CollidableObj obj, List <Vector2>[] axis) { /*if (!(((BuffableObject)obj).useStat(StatTypes.Invincibility) > 0)) * { * ((Character)obj).takeDamage((float)useStat(StatTypes.Attack)); * obj.setVelocity(new Vector2(0, obj.Velocity.Y)); * obj.addVelocity(new Vector2((float)((Character)obj).calculateStat(StatTypes.Movement) * Math.Sign(obj.Position.X - Position.X), 0)); * obj.direction = (Direction)(-Math.Sign(obj.Position.X - Position.X)); * }*/ }
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)]); }
public CollidableObj(CollidableObj obj) { Position = obj.Position; Velocity = obj.Velocity; direction = obj.direction; collisionType = obj.collisionType; foreach (Vector2 vec in obj.collisionArea) { collisionArea.Add(vec); } }
public void setPath(PathWaypoint newPath, AIState state, CollidableObj obj = null) { timeSincePathUpdate = 0; path = newPath; targetObj = obj; jumped = false; if (this.state != AIState.Chasing && state == AIState.Chasing) { agroTimer = 0; tiredIntervals = 1; } this.state = state; }
sealed public void collide(CollidableObj obj, List <Vector2>[] axis) { if (character != null && obj.collisionType == CollisionTypes.Enemy && attackID != null && !((Character)obj).getAttackedByID((TimeSpan)attackID)) { Character target = (Character)obj; target.addAttackID((TimeSpan)attackID); target.takeDamage(character.useAttackDamage(target)); if (target.calculateStat(StatTypes.Health) == 0) { character.addKillCount(); character.useStat(StatTypes.Kills); } attackID = null; } }
public void collide(CollidableObj obj, List <Vector2>[] axis) { foreach (Vector2 vec in axis[0]) { if (vec.X != 0) { deactivate(); character.attack(); } } if (axis[0].Count == 0) { deactivate(); character.attack(); } }
private List <Vector2> getCollisionAxis(CollidableObj obj, List <Vector2> foundAxis = null) { List <Vector2> axis = new List <Vector2>(); for (int i = 0; i < obj.collisionArea.Count; ++i) { Vector2 p1 = obj.collisionArea[i] * new Vector2((int)obj.direction, 1) + obj.Position; Vector2 p2 = obj.collisionArea[(i == obj.collisionArea.Count - 1) ? 0 : i + 1] * new Vector2((int)obj.direction, 1) + obj.Position; float xDif = p1.X - p2.X; float yDif = p1.Y - p2.Y; double magnitude = Math.Sqrt(Math.Pow(xDif, 2) + Math.Pow(yDif, 2)); Vector2 curAxis = new Vector2(-yDif / (float)magnitude, xDif / (float)magnitude); if (foundAxis != null && foundAxis.IndexOf(curAxis) == -1) { axis.Add(curAxis); } } return(axis); }
public void handleCollision(CollidableObj obj, float timeDisplacement) { List <Vector2>[] collisionAxis = hasCollision(obj, timeDisplacement); if (collisionAxis != null) { if (collisionType > obj.collisionType) { collide(obj, collisionAxis); } else if (collisionType < obj.collisionType) { obj.collide(this, collisionAxis); } else { collide(obj, collisionAxis); obj.collide(this, collisionAxis); } } }
public void collide(CollidableObj obj, List <Vector2>[] axis) { }
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); }
public List <Vector2>[] hasCollision(CollidableObj obj, float timeDisplacement) { if (collisionArea.Count == 0 || obj.collisionArea.Count == 0) { return(null); } List <Vector2> axis = new List <Vector2>(); axis.AddRange(getCollisionAxis(this)); axis.AddRange(getCollisionAxis(obj, axis)); foreach (Vector2 curAxis in axis) { double[] obj1MinMax = getObjectMinMax(curAxis, this, timeDisplacement, true); double[] obj2MinMax = getObjectMinMax(curAxis, obj, timeDisplacement, true); double[] preMoveObj1MinMax = getObjectMinMax(curAxis, this); double[] preMoveObj2MinMax = getObjectMinMax(curAxis, obj); if (preMoveObj1MinMax[0] > preMoveObj2MinMax[1] && obj1MinMax[1] < obj2MinMax[0] || // If obj1 min was greater then obj2 max and now obj1 max is less then obj2 min preMoveObj1MinMax[1] < preMoveObj2MinMax[0] && obj1MinMax[0] > obj2MinMax[1] // If obj1 max was less then obj2 min and now obj1 min is greater then obj2 max //|| preMoveObj1MinMax[0] > preMoveObj2MinMax[0] && preMoveObj1MinMax[0] < preMoveObj2MinMax[1] // Obj1 min is colliding with obj2 //|| preMoveObj1MinMax[1] > preMoveObj2MinMax[0] && preMoveObj1MinMax[1] < preMoveObj2MinMax[1] // Obj1 max is colliding with obj2 ) { continue; } if (obj1MinMax[0] > obj2MinMax[1] || obj1MinMax[1] < obj2MinMax[0]) { return(null); } } List <Vector2>[] collisionAxis = new List <Vector2> [2]; collisionAxis[0] = new List <Vector2>(); // Distance to obj collisionAxis[1] = new List <Vector2>(); foreach (Vector2 curAxis in axis) { double[] preMoveObj1MinMax = getObjectMinMax(curAxis, this); double[] preMoveObj2MinMax = getObjectMinMax(curAxis, obj); if (preMoveObj1MinMax[0] >= preMoveObj2MinMax[1] /* || obj1MinMax[1] < obj2MinMax[0]*/) { collisionAxis[0].Add(curAxis * new Vector2(-1, -1)); float distance = (float)((preMoveObj1MinMax[0] >= preMoveObj2MinMax[1]) ? preMoveObj1MinMax[0] - preMoveObj2MinMax[1] : preMoveObj2MinMax[0] - preMoveObj1MinMax[1]); collisionAxis[1].Add(new Vector2(distance * curAxis.X, distance * curAxis.Y)); } } if (collisionAxis[0].Count == 2) { if (obj.Velocity * collisionAxis[0][0] + collisionAxis[0][0] * this.Velocity != new Vector2() && obj.Velocity * collisionAxis[0][1] + collisionAxis[0][1] * this.Velocity != new Vector2()) { Vector2 axis0 = obj.Velocity * collisionAxis[0][0] + collisionAxis[0][0] * this.Velocity; Vector2 axis1 = obj.Velocity * collisionAxis[0][1] + collisionAxis[0][1] * this.Velocity; if (axis0.X != 0 && axis0.X > axis1.Y || axis0.Y != 0 && axis0.Y > axis1.X) { collisionAxis[0].RemoveAt(0); collisionAxis[1].RemoveAt(0); } else if (axis0 == axis1) { if (axis0.X == 0) { collisionAxis[0].RemoveAt(1); collisionAxis[1].RemoveAt(1); } else { collisionAxis[0].RemoveAt(0); collisionAxis[1].RemoveAt(0); } } else { collisionAxis[0].RemoveAt(1); collisionAxis[1].RemoveAt(1); } return(collisionAxis); } if (collisionAxis[1][0].X == 0 && collisionAxis[1][0].Y == 0 && obj.Velocity * collisionAxis[0][0] == new Vector2() && this.Velocity * collisionAxis[0][0] == new Vector2() || collisionAxis[1][1].X == 0 && collisionAxis[1][1].Y == 0 && obj.Velocity * collisionAxis[0][1] == new Vector2() && this.Velocity * collisionAxis[0][1] == new Vector2()) { for (int i = collisionAxis[0].Count - 1; i >= 0; --i) { if (obj.Velocity * collisionAxis[0][i] != new Vector2() || this.Velocity * collisionAxis[0][i] != new Vector2()) { collisionAxis[0].RemoveAt(i); collisionAxis[1].RemoveAt(i); } } } return((collisionAxis[0].Count > 0) ? collisionAxis : null); } return(collisionAxis); }