protected override void LoadContent() { debugDraw = new DebugDraw(GraphicsDevice); box1 = new CollidableObject(new Vector2(50, 50)) { Position = new Vector2(620, 250), Velocity = new Vector2(20, 150), Name = "Box", }; int vertexCount = 10; float radius = 150; List <Vector2> vertices = new List <Vector2>(); for (int i = 0; i < vertexCount; i++) { float radians = i / (float)vertexCount * MathHelper.TwoPi; var v = new Vector2(radius * (float)Math.Cos(radians), radius * (float)Math.Sin(radians)); vertices.Add(v); } //box2 = new CollidableObject(new Vector2(500, 25)) box2 = new CollidableObject(vertices) { Position = new Vector2(640, 500), //Velocity = new Vector2(20, -50), Name = "Object", Velocity = new Vector2(0, -10), }; }
private static bool FindIntervalIntersection(CollidableObject object1, CollidableObject object2, Vector2 velocity, Vector2 axis, out float time) { float min0, max0, min1, max1; object1.CalculateInterval(axis, out min0, out max0); object2.CalculateInterval(axis, out min1, out max1); float d0 = min0 - max1; float d1 = min1 - max0; if (Utility.ApproximatelyZero(d0)) { d0 = 0; } if (Utility.ApproximatelyZero(d1)) { d1 = 0; } if (d0 < 0 && d1 < 0) { time = Math.Max(d0, d1); return(true); } float v = Vector2.Dot(velocity, axis); if (Utility.ApproximatelyZero(v)) { time = float.NegativeInfinity; return(false); } float t0 = -d0 / v; float t1 = d1 / v; if (t0 <= 0 && t1 <= 0) { time = float.NegativeInfinity; return(false); } if (t0 > t1) { float temp = t0; t0 = t1; t1 = temp; } time = (t0 >= 0) ? t0 : t1; if (time >= 1) { return(false); } return(true); }
protected override void Update(GameTime gameTime) { base.Update(gameTime); Vector2 newPosition = Vector2.Zero; Vector2 newVelocity = Vector2.Zero; var keyboardState = Keyboard.GetState(); if (keyboardState.IsKeyDown(Keys.Left)) { newPosition.X = -1; } else if (keyboardState.IsKeyDown(Keys.Right)) { newPosition.X = 1; } if (keyboardState.IsKeyDown(Keys.Up)) { newPosition.Y = -1; } else if (keyboardState.IsKeyDown(Keys.Down)) { newPosition.Y = 1; } if (keyboardState.IsKeyDown(Keys.A)) { newVelocity.X = -1; } else if (keyboardState.IsKeyDown(Keys.D)) { newVelocity.X = 1; } if (keyboardState.IsKeyDown(Keys.W)) { newVelocity.Y = -1; } else if (keyboardState.IsKeyDown(Keys.S)) { newVelocity.Y = 1; } if (keyboardState.IsKeyDown(Keys.P)) { pauseRotation = true; } else if (keyboardState.IsKeyDown(Keys.U)) { pauseRotation = false; } box1.Velocity += newVelocity; box1.Position += newPosition; if (!pauseRotation) { box1.Rotation += (float)gameTime.ElapsedGameTime.TotalSeconds; box2.Rotation -= (float)gameTime.ElapsedGameTime.TotalSeconds / 2; } box1.UpdateWorldSpaceVertices(); box2.UpdateWorldSpaceVertices(); if (CollidableObject.FindCollision(box1, box2, out Vector2 axis, out float time)) { box1.IsColliding = true; box1.CollisionTime = time; box1.PushVector = axis * -time; box2.IsColliding = true; box2.CollisionTime = Math.Max(time, 0); box2.PushVector = axis; }
public static bool FindCollision(CollidableObject object1, CollidableObject object2, out Vector2 axis, out float time) { Vector2 velocity = object1.Velocity - object2.Velocity; axis = default(Vector2); time = default(float); Vector2 velocityNormal = Vector2.Normalize(new Vector2(velocity.Y, -velocity.X)); float tempTime; // FIXME: if velocity magnitude is zero, we can skip this // FIXME: maybe we should test this last, if we're overlapping it's not needed if (!FindIntervalIntersection(object1, object2, velocity, velocityNormal, out tempTime)) { return(false); } float maxNegativeTime = float.MinValue; float maxPositiveTime = float.MinValue; Vector2 maxNegativeAxis = Vector2.Zero; Vector2 maxPositiveAxis = Vector2.Zero; bool futureCollision = false; foreach (var testAxis in object1.CollisionAxes) { if (!FindIntervalIntersection(object1, object2, velocity, testAxis, out tempTime)) { return(false); } if (tempTime >= 0) { if (tempTime > maxPositiveTime) { maxPositiveTime = tempTime; maxPositiveAxis = testAxis; } futureCollision = true; } else { if (tempTime > maxNegativeTime) { maxNegativeTime = tempTime; maxNegativeAxis = testAxis; } } } foreach (var testAxis in object2.CollisionAxes) { if (!FindIntervalIntersection(object1, object2, velocity, testAxis, out tempTime)) { return(false); } if (tempTime >= 0) { if (tempTime > maxPositiveTime) { maxPositiveTime = tempTime; maxPositiveAxis = testAxis; } futureCollision = true; } else { if (tempTime > maxNegativeTime) { maxNegativeTime = tempTime; maxNegativeAxis = testAxis; } } } if (futureCollision) { time = maxPositiveTime; axis = maxPositiveAxis; } else { time = maxNegativeTime; axis = maxNegativeAxis; } if (Vector2.Dot(object1.Position - object2.Position, axis) < 0.0f) { axis *= -1.0f; } return(true); }