예제 #1
0
        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);
        }
예제 #3
0
        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);
        }