public static Vector2[] displacementDueToMass(collisionShape a, collisionShape b, Vector2 aToMove) { Vector2[] ret = new Vector2[2]; int aDirectionX; int aDirectionY; float aX = (aToMove.X * ((float)b.mass / (a.mass + b.mass))); if (aX > 0) { aDirectionX = (int)Math.Ceiling(aX); } else { aDirectionX = (int)Math.Floor(aX); } float aY = (aToMove.Y * ((float)b.mass / (a.mass + b.mass))); if (aY > 0) { aDirectionY = (int)Math.Ceiling(aY); } else { aDirectionY = (int)Math.Floor(aY); } ret[0] = new Vector2(aDirectionX,aDirectionY); ret[1] = new Vector2(((int)aToMove.X - aDirectionX),((int)aToMove.Y - aDirectionY)); return ret; }
public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; a = new collisionShape(A, new Vector2(A.Width / 2, A.Height / 2), 0,200); b = new collisionShape(B, new Vector2(B.Width / 2, B.Height / 2), 0,500); c = new collisionShape(new Vector2(200, 200), 10,900); d = new collisionShape(new Vector2(300,300),20,800); player = new Rectangle(100, 100, 20, 40); }
public static Vector2 intersectCircles(collisionShape a, collisionShape b) { float dist = Vector2.Distance(a.location, b.location); if (dist > a.radius + b.radius) { return Vector2.Zero; } else { return Vector2.Normalize(b.location - a.location) * (dist - (a.radius + b.radius)); } }
public static Vector2 circleLineDetect(Vector2 lineA, Vector2 lineB, collisionShape circle) { Vector2 v = lineB - (lineA); Vector2 w = circle.location - (lineA); float wDotv = Vector2.Dot(w, v); float t = Vector2.Dot(w, v) / Vector2.Dot(v, v); t = MathHelper.Clamp(t, 0, 1); Vector2 p = lineA + v * t; if (Vector2.DistanceSquared(p, circle.location) < circle.radius * circle.radius) { Vector2 towardsp = Vector2.Normalize(p - circle.location); return circle.location + (circle.radius * towardsp) - p; } return Vector2.Zero; }
//SAT for two rotated rectangles // 1st rectangle is weaker so is moved out by return vector2 public static Vector2 intersectRectangles(collisionShape a, collisionShape b) { collisionShape ar = new collisionShape(new Rectangle((int)(a.r.X - a.rotatePoint.X), (int)(a.r.Y - a.rotatePoint.Y), a.r.Width, a.r.Height), a.rotatePoint, a.rotation,0); //Rotated Vector points of Rectangle A Vector2 aUL = UpperLeftCorner(ar); Vector2 aUR = UpperRightCorner(ar); Vector2 aLL = LowerLeftCorner(ar); Vector2 aLR = LowerRightCorner(ar); Vector2[] aPoints = new Vector2[] { aUL, aUR, aLL, aLR }; todraw5 = aUL; todraw6 = aUR; todraw7 = aLL; todraw8 = aLR; int aLeft = (int)Math.Min(Math.Min(aUL.X, aUR.X), Math.Min(aLL.X, aLR.X)); int aTop = (int)Math.Min(Math.Min(aUL.Y, aUR.Y), Math.Min(aLL.Y, aLR.Y)); int aRight = (int)Math.Max(Math.Max(aUL.X, aUR.X), Math.Max(aLL.X, aLR.X)); int aBottom = (int)Math.Max(Math.Max(aUL.Y, aUR.Y), Math.Max(aLL.Y, aLR.Y)); Rectangle aNoRotate = new Rectangle(aLeft, aTop, aRight - aLeft, aBottom - aTop); collisionShape br = new collisionShape(new Rectangle((int)(b.r.X - b.rotatePoint.X), (int)(b.r.Y - b.rotatePoint.Y), b.r.Width, b.r.Height), b.rotatePoint, b.rotation,0); //Rotated Vector points of Rectangle B Vector2 bUL = UpperLeftCorner(br); Vector2 bUR = UpperRightCorner(br); Vector2 bLL = LowerLeftCorner(br); Vector2 bLR = LowerRightCorner(br); Vector2[] bPoints = new Vector2[] { bUL, bUR, bLL, bLR }; int bLeft = (int)Math.Min(Math.Min(bUL.X, bUR.X), Math.Min(bLL.X, bLR.X)); int bTop = (int)Math.Min(Math.Min(bUL.Y, bUR.Y), Math.Min(bLL.Y, bLR.Y)); int bRight = (int)Math.Max(Math.Max(bUL.X, bUR.X), Math.Max(bLL.X, bLR.X)); int bBottom = (int)Math.Max(Math.Max(bUL.Y, bUR.Y), Math.Max(bLL.Y, bLR.Y)); Rectangle bNoRotate = new Rectangle(bLeft, bTop, bRight - bLeft, bBottom - bTop); //Checks initially for the bounding rectangles non rotated. if (!intersectRectanglesNoRotate(aNoRotate, bNoRotate)) { return Vector2.Zero; } todraw1 = bUL; todraw2 = bUR; todraw3 = bLL; todraw4 = bLR; List<Vector2> aRectangleAxis = new List<Vector2>(); aRectangleAxis.Add(aUR - aUL); aRectangleAxis.Add(aUR - aLR); aRectangleAxis.Add(bUL - bLL); aRectangleAxis.Add(bUL - bUR); //Cycle through all of the Axis we need to check. If a collision does not occur //on ALL of the Axis, then a collision is NOT occurring. We can then exit out //immediately and notify the calling function that no collision was detected. If //a collision DOES occur on ALL of the Axis, then there is a collision occurring //between the rotated rectangles. We know this to be true by the Seperating Axis Theorem Vector2 smallest = new Vector2(10000, 10000); foreach (Vector2 aAxis in aRectangleAxis) { Vector2 res = IsAxisCollision(aPoints, bPoints, aAxis); if (res == Vector2.Zero) { return Vector2.Zero; } else { if (Math.Pow(res.X, 2) + Math.Pow(res.Y, 2) < Math.Pow(smallest.X, 2) + Math.Pow(smallest.Y, 2)) { smallest = res; } } } return smallest; }
private static Vector2 intersectCircleRectangle(collisionShape circle, collisionShape rectangle) { collisionShape rectangle2 = new collisionShape(new Rectangle((int)(rectangle.r.X - rectangle.rotatePoint.X), (int)(rectangle.r.Y - rectangle.rotatePoint.Y), rectangle.r.Width, rectangle.r.Height), rectangle.rotatePoint, rectangle.rotation,0); //Rotated Vector points of Rectangle Vector2 rUL = UpperLeftCorner(rectangle2); Vector2 rUR = UpperRightCorner(rectangle2); Vector2 rLL = LowerLeftCorner(rectangle2); Vector2 rLR = LowerRightCorner(rectangle2); Vector2[] bPoints = new Vector2[] { rUL, rUR, rLL, rLR }; int bLeft = (int)Math.Min(Math.Min(rUL.X, rUR.X), Math.Min(rLL.X, rLR.X)); int bTop = (int)Math.Min(Math.Min(rUL.Y, rUR.Y), Math.Min(rLL.Y, rLR.Y)); int bRight = (int)Math.Max(Math.Max(rUL.X, rUR.X), Math.Max(rLL.X, rLR.X)); int bBottom = (int)Math.Max(Math.Max(rUL.Y, rUR.Y), Math.Max(rLL.Y, rLR.Y)); //if (!intersectRectanglesNoRotate(new Rectangle(bLeft, bTop, bRight - bLeft, bBottom - bTop), new Rectangle((int)(circle.location.X - circle.radius), (int)(circle.location.Y - circle.radius), (int)circle.radius * 2, (int)circle.radius * 2))) //{ // return Vector2.Zero; //} Vector2 Normalisedvec; //Now we normalise the rectangle and circle by rotating the two objects by the rectangles rotation Vector2 rNUL = helper.rotatePoint2(rUL,new Vector2(rectangle2.r.X,rectangle2.r.Y),-rectangle2.rotation); Vector2 rNUR = helper.rotatePoint2(rUR,new Vector2(rectangle2.r.X,rectangle2.r.Y),-rectangle2.rotation); Vector2 rNLL = helper.rotatePoint2(rLL,new Vector2(rectangle2.r.X,rectangle2.r.Y),-rectangle2.rotation); Vector2 rNLR = helper.rotatePoint2(rLR, new Vector2(rectangle2.r.X, rectangle2.r.Y), -rectangle2.rotation); Rectangle recNormal = new Rectangle((int)rNUL.X, (int)rNUL.Y, (int)(rNUR.X - rNUL.X),(int)( rNLL.Y - rNUL.Y)); Vector2 circleLoc = helper.rotatePoint2(circle.location, new Vector2(rectangle2.r.X, rectangle2.r.Y), -rectangle2.rotation); todraw9 = circleLoc; todraw6 = new Vector2(recNormal.Right, recNormal.Top); //Now we check for voronoi regions on the rectangle bool voronoid = false; Vector2 vertexVoronoi; //See if cirlce point fits in any voronoi region if (circleLoc.X < recNormal.Left && circleLoc.Y < recNormal.Top) { vertexVoronoi = rNUL; voronoid = true; } if (circleLoc.X > recNormal.Right && circleLoc.Y < recNormal.Top) { vertexVoronoi = rNUR; voronoid = true; } if (circleLoc.X < recNormal.Left && circleLoc.Y > recNormal.Bottom) { vertexVoronoi = rNLL; voronoid = true; } if (circleLoc.X > recNormal.Right && circleLoc.Y > recNormal.Bottom) { vertexVoronoi = rNLR; voronoid = true; } if (!voronoid) { circle.rotation = 0.0f; Rectangle circleRec = new Rectangle((int)(circleLoc.X - circle.radius), (int)(circleLoc.Y - circle.radius), (int)circle.radius * 2, (int)circle.radius * 2); Normalisedvec = intersectRectangles(new collisionShape(circleRec, Vector2.Zero, 0,0), new collisionShape(recNormal, Vector2.Zero, 0,0)); } else { circle.rotation = (float)Math.PI / 4; Rectangle circleRec = new Rectangle((int)(circleLoc.X), (int)(circleLoc.Y ), (int)circle.radius * 2, (int)circle.radius * 2); Normalisedvec = intersectRectangles(new collisionShape(circleRec, new Vector2(circle.radius,circle.radius), (float)Math.PI / 4,0), new collisionShape(recNormal, Vector2.Zero, 0,0)); } return helper.rotatePoint2(Normalisedvec, Vector2.Zero, rectangle.rotation); }
public static Vector2 UpperRightCorner(collisionShape a) { Vector2 aUpperRight = new Vector2(a.r.Right, a.r.Top); aUpperRight = RotatePoint(aUpperRight, aUpperRight + new Vector2(-(a.r.Width - a.rotatePoint.X), a.rotatePoint.Y), a.rotation); return aUpperRight; }
public static Vector2 UpperLeftCorner(collisionShape a) { Vector2 aUpperLeft = new Vector2(a.r.Left, a.r.Top); aUpperLeft = RotatePoint(aUpperLeft, aUpperLeft + a.rotatePoint, a.rotation); return aUpperLeft; }
public static Vector2 ShapeSelector(collisionShape a, collisionShape b) { if (a.Flag == 0 && b.Flag == 0) { return intersectRectangles(a, b); } if (a.Flag == 0 && b.Flag == 1) { return -(intersectCircleRectangle(a, b)); } if (a.Flag == 1 && b.Flag == 0) { return intersectCircleRectangle(a, b); } if (a.Flag == 1 && b.Flag == 1) { return intersectCircles(a, b); } return Vector2.Zero; }
public static Vector2 LowerRightCorner(collisionShape a) { Vector2 aLowerRight = new Vector2(a.r.Right, a.r.Bottom); aLowerRight = RotatePoint(aLowerRight, aLowerRight + new Vector2(-(a.r.Width - a.rotatePoint.X), -(a.r.Height - a.rotatePoint.Y)), a.rotation); return aLowerRight; }
public static Vector2 LowerLeftCorner(collisionShape a) { Vector2 aLowerLeft = new Vector2(a.r.Left, a.r.Bottom); aLowerLeft = RotatePoint(aLowerLeft, aLowerLeft + new Vector2(a.rotatePoint.X, -(a.r.Height - a.rotatePoint.Y)), a.rotation); return aLowerLeft; }