private static void SolidSquareCollision(SquareCollisionBox ia, SquareCollisionBox ib, out CollisionResolutionData dataA, out CollisionResolutionData dataB) { dataA = new CollisionResolutionData(); dataB = new CollisionResolutionData(); dataA.obj = ib; dataB.obj = ia; BasePhysObject objectA = ia; BasePhysObject objectB = ib; var av = objectA.GetVelocity(); var bv = objectB.GetVelocity(); //Get inverse vectors var inverseA = Vector.Multiply(-1, av); var inverseB = Vector.Multiply(-1, bv); //Combined magnitude var tXMag = Math.Abs(inverseA.X - inverseB.X); var tYMag = Math.Abs(inverseA.Y - inverseB.Y); var absXMag = Math.Abs(inverseA.X) + Math.Abs(inverseB.X); var absYMag = Math.Abs(inverseA.Y) + Math.Abs(inverseB.Y); double deltaX; double deltaY; if (av.X < 0 && bv.X < 0) { deltaX = av.X < bv.X ? Math.Abs(ib.Right - ia.Left) : Math.Abs(ib.Left - ia.Right); } else if (av.X > 0 && bv.X > 0) { deltaX = av.X > bv.X ? Math.Abs(ib.Left - ia.Right) : Math.Abs(ib.Right - ia.Left); } else { deltaX = av.X > 0 ? Math.Abs(ib.Left - ia.Right) : Math.Abs(ib.Right - ia.Left); } var aMount = false; var bMount = false; if (av.Y < 0 && bv.Y < 0) { if (av.Y > bv.Y) { deltaY = Math.Abs(ib.Bottem - ia.Top); bMount = true; } else { deltaY = Math.Abs(ib.Top - ia.Bottem); aMount = true; } } else if (av.Y > 0 && bv.Y > 0) { if (av.Y < bv.Y) { deltaY = Math.Abs(ib.Top - ia.Bottem); aMount = true; } else { deltaY = Math.Abs(ib.Bottem - ia.Top); bMount = true; } } else { if (av.Y > 0) { deltaY = Math.Abs(ib.Top - ia.Bottem); aMount = true; } else { deltaY = Math.Abs(ib.Bottem - ia.Top); bMount = true; } } //What we do here is get the ratio of movement to distance //between the closest edges of the two objects double xRatio = 0; double yRatio = 0; xRatio = deltaX / tXMag; yRatio = deltaY / tYMag; //The distance between the colliding edges of the objects after collision resolution //A buffer of 0.0 would result in the colliding edges still being ontop of eachother after collision resolution var collisionBuffer = 0.01; //The lower ratio indicates which side hit first if (xRatio < yRatio) { var xa = 0.0; var xb = 0.0; //apply correction if (ia.CollisionObjectType == CollisionObjectType.Static) { xb = inverseA.X / absXMag * (deltaX + collisionBuffer) + inverseB.X / absXMag * deltaX; } else if (ib.CollisionObjectType == CollisionObjectType.Static) { xa = inverseA.X / absXMag * (deltaX + collisionBuffer) + inverseB.X / absXMag * deltaX; } else { xa = inverseA.X / absXMag * (deltaX + collisionBuffer); xb = inverseB.X / absXMag * (deltaX + collisionBuffer); } dataA.PositionChange = new Vector(xa, 0); dataB.PositionChange = new Vector(xb, 0); dataA.CollisionAxisX = true; dataB.CollisionAxisX = true; } else { var ya = 0.0; var yb = 0.0; //apply correction if (ia.CollisionObjectType == CollisionObjectType.Static) { yb = inverseA.Y / absYMag * (deltaY + collisionBuffer) + inverseB.Y / absYMag * deltaY; } else if (ib.CollisionObjectType == CollisionObjectType.Static) { ya = inverseA.Y / absYMag * (deltaY + collisionBuffer) + inverseB.Y / absYMag * deltaY; } else { ya = inverseA.Y / absYMag * (deltaY + collisionBuffer); yb = inverseB.Y / absYMag * (deltaY + collisionBuffer); } dataA.PositionChange = new Vector(0, ya); dataB.PositionChange = new Vector(0, yb); dataA.CollisionAxisY = true; dataB.CollisionAxisY = true; //Do Mounting if (aMount && ia.CollisionObjectType != CollisionObjectType.Static) { dataA.Mount = true; } if (bMount && ib.CollisionObjectType != CollisionObjectType.Static) { dataB.Mount = true; } } }
/// <summary> /// Axis-Aligned Bounding Box collision /// </summary> /// <param name="rectA">Box 1</param> /// <param name="rectB">Box 2</param> /// <returns></returns> private static bool Aabb(SquareCollisionBox rectA, SquareCollisionBox rectB) { return(!(rectA.Right < rectB.Left) && !(rectA.Bottem < rectB.Top) && !(rectA.Left > rectB.Right) && !(rectA.Top > rectB.Bottem)); }