private static void HandleCollision(CollisionCircle circle1, CollisionCircle circle2) { if (circle1.IsStatic && circle2.IsStatic) { return; } Vector2 d = circle1.Center - circle2.Center; float distance = d.Length(); // If two circles collide if (circle1.Radius + circle2.Radius > distance) { if (distance == 0) { d.X = r.Next(-200, 201); d.Y = r.Next(-200, 201); if (d != Vector2.Zero) { d.Normalize(); } } else { d /= distance; } // Static objects do not move, so only move back the non-static one if (circle1.IsStatic) { d *= -1; float distToPush = circle1.Radius + circle2.Radius - distance + OFFSET; circle2.Center += distToPush * d; } else if (circle2.IsStatic) { Vector2 direction = d / distance; float distToPush = circle1.Radius + circle2.Radius - distance + OFFSET; circle1.Center += distToPush * d; } // If both objects are non-static, move them both back evenly else { float distToPush = (circle1.Radius + circle2.Radius - distance) / 2 + OFFSET; circle1.Center += distToPush * d; circle2.Center -= distToPush * d; } } }
private static void HandleCollision(CollisionCircle circle, CollisionRect rect) { if(circle.IsStatic && rect.IsStatic) return; // Reference: stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection/402010#402010 Vector2 d = circle.Center - rect.Center; d = new Vector2(Math.Abs(d.X), Math.Abs(d.Y)); Vector2 cd = new Vector2(d.X - rect.Width * 0.5f, d.Y - rect.Depth * 0.5f); float cornerDistSqr = cd.LengthSquared(); // If circle and rectangle collide if(d.X <= rect.Width / 2 + circle.Radius && d.Y <= rect.Depth / 2 + circle.Radius || cornerDistSqr <= circle.Radius * circle.Radius) { // If circle and rectangle centers completely overlap, // slightly move one of the object's center so they don't completely overlap if(d.Length() == 0) { d.X = r.Next(-200, 201); d.Y = r.Next(-200, 201); if(d != Vector2.Zero) { d.Normalize(); d *= 0.1f; } if(circle.IsStatic) rect.Center += d; else circle.Center += d; HandleCollision(circle, rect); } // Create a collision boundary around the rectangle, in which collision occurs float top = rect.Center.Y + rect.Depth / 2 + circle.Radius; float bottom = rect.Center.Y - rect.Depth / 2 - circle.Radius; float left = rect.Center.X - rect.Width / 2 - circle.Radius; float right = rect.Center.X + rect.Width / 2 + circle.Radius; float distToTop = Math.Abs(circle.Center.Y - top); float distToBottom = Math.Abs(circle.Center.Y - bottom); float distToLeft = Math.Abs(circle.Center.X - left); float distToRight = Math.Abs(circle.Center.X - right); // Choose the closest distance to the collision boundary as the pushing direction Vector2 pushAmount = new Vector2(); // How much should be pushed relative to circle float min = Math.Min(Math.Min(Math.Min(distToTop, distToBottom), distToLeft), distToRight); pushAmount.Y += min == distToTop ? distToTop + OFFSET : 0; pushAmount.Y += min == distToBottom ? -distToBottom - OFFSET : 0; pushAmount.X += min == distToLeft ? -distToLeft - OFFSET : 0; pushAmount.X += min == distToRight ? distToRight + OFFSET : 0; // Only move the non-static object if(rect.IsStatic) circle.Center += pushAmount; else if(circle.IsStatic) rect.Center -= pushAmount; else { circle.Center += pushAmount / 2; rect.Center -= pushAmount / 2; } } }
private static void HandleCollision(CollisionCircle circle1, CollisionCircle circle2) { if(circle1.IsStatic && circle2.IsStatic) return; Vector2 d = circle1.Center - circle2.Center; float distance = d.Length(); // If two circles collide if(circle1.Radius + circle2.Radius > distance) { if(distance == 0) { d.X = r.Next(-200, 201); d.Y = r.Next(-200, 201); if(d != Vector2.Zero) d.Normalize(); } else { d /= distance; } // Static objects do not move, so only move back the non-static one if(circle1.IsStatic) { d *= -1; float distToPush = circle1.Radius + circle2.Radius - distance + OFFSET; circle2.Center += distToPush * d; } else if(circle2.IsStatic) { Vector2 direction = d / distance; float distToPush = circle1.Radius + circle2.Radius - distance + OFFSET; circle1.Center += distToPush * d; } // If both objects are non-static, move them both back evenly else { float distToPush = (circle1.Radius + circle2.Radius - distance) / 2 + OFFSET; circle1.Center += distToPush * d; circle2.Center -= distToPush * d; } } }
private static void HandleCollision(CollisionCircle circle, CollisionRect rect) { if (circle.IsStatic && rect.IsStatic) { return; } // Reference: stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection/402010#402010 Vector2 d = circle.Center - rect.Center; d = new Vector2(Math.Abs(d.X), Math.Abs(d.Y)); Vector2 cd = new Vector2(d.X - rect.Width * 0.5f, d.Y - rect.Depth * 0.5f); float cornerDistSqr = cd.LengthSquared(); // If circle and rectangle collide if (d.X <= rect.Width / 2 + circle.Radius && d.Y <= rect.Depth / 2 + circle.Radius || cornerDistSqr <= circle.Radius * circle.Radius) { // If circle and rectangle centers completely overlap, // slightly move one of the object's center so they don't completely overlap if (d.Length() == 0) { d.X = r.Next(-200, 201); d.Y = r.Next(-200, 201); if (d != Vector2.Zero) { d.Normalize(); d *= 0.1f; } if (circle.IsStatic) { rect.Center += d; } else { circle.Center += d; } HandleCollision(circle, rect); } // Create a collision boundary around the rectangle, in which collision occurs float top = rect.Center.Y + rect.Depth / 2 + circle.Radius; float bottom = rect.Center.Y - rect.Depth / 2 - circle.Radius; float left = rect.Center.X - rect.Width / 2 - circle.Radius; float right = rect.Center.X + rect.Width / 2 + circle.Radius; float distToTop = Math.Abs(circle.Center.Y - top); float distToBottom = Math.Abs(circle.Center.Y - bottom); float distToLeft = Math.Abs(circle.Center.X - left); float distToRight = Math.Abs(circle.Center.X - right); // Choose the closest distance to the collision boundary as the pushing direction Vector2 pushAmount = new Vector2(); // How much should be pushed relative to circle float min = Math.Min(Math.Min(Math.Min(distToTop, distToBottom), distToLeft), distToRight); pushAmount.Y += min == distToTop ? distToTop + OFFSET : 0; pushAmount.Y += min == distToBottom ? -distToBottom - OFFSET : 0; pushAmount.X += min == distToLeft ? -distToLeft - OFFSET : 0; pushAmount.X += min == distToRight ? distToRight + OFFSET : 0; // Only move the non-static object if (rect.IsStatic) { circle.Center += pushAmount; } else if (circle.IsStatic) { rect.Center -= pushAmount; } else { circle.Center += pushAmount / 2; rect.Center -= pushAmount / 2; } } }