Ejemplo n.º 1
0
        public CollisionResult SolveCollision(Body bodyA, Body bodyB)
        {
            BoxShape  boxA = bodyA.Shape as BoxShape;
            BoxShape  boxB = bodyB.Shape as BoxShape;
            Transform tfA  = bodyA.Transform;
            Transform tfB  = bodyB.Transform;


            // TODO miten toi position saatais keskelle suoraan
#if !COLLISION_USE_CENTER_POINT
            Vector2 centerA = tfA.Position + new Vector2(boxA.HalfWidth, boxA.HalfHeight);
            Vector2 centerB = tfB.Position + new Vector2(boxB.HalfWidth, boxB.HalfHeight);
#endif
#if COLLISION_USE_CENTER_POINT
            Vector2 centerA = tfA.Position;
            Vector2 centerB = tfB.Position;
#endif

            boxA.CalculateOrientation(ref tfA, out axesToCheck[0]);
            boxB.CalculateOrientation(ref tfB, out axesToCheck[1]);
            axesToCheck[2] = new Vector2(-axesToCheck[0].Y, axesToCheck[0].X);
            axesToCheck[3] = new Vector2(-axesToCheck[1].Y, axesToCheck[1].X);

            Vector2 distance          = centerA - centerB;
            float   projectedDistance = 0;
            float   minPenetration    = float.MaxValue;

            Vector2 mtv = Vector2.Zero; // minium translation vector
            for (int i = 0; i < axesToCheck.Length; i++)
            {
                Vector2 projectionA, projectionB;
                projectedDistance = Math.Abs(Vector2.Dot(distance, axesToCheck[i]));
                boxA.Project(ref tfA, ref axesToCheck[i], out projectionA);
                boxB.Project(ref tfB, ref axesToCheck[i], out projectionB);

                float aSize       = Math.Abs(projectionA.X) + Math.Abs(projectionA.Y);
                float bSize       = Math.Abs(projectionB.X) + Math.Abs(projectionB.Y);
                float abSize      = aSize + bSize;
                float penetration = abSize - projectedDistance;

                // seperate axis, ei collisionia
                if (penetration <= 0)
                {
                    return(CollisionResult.NoCollision);
                }

                if (Math.Abs(penetration) < Math.Abs(minPenetration))
                {
                    minPenetration = penetration;
                    mtv            = axesToCheck[i];
                }
            }
            // distance määrittää liikkumisen suunnan
            if (Vector2.Dot(distance, mtv) < 0f)
            {
                mtv = -mtv;
            }
            // seperating axis löyty, joten bodyt törmää
            return(new CollisionResult()
            {
                Us = bodyA,
                Them = bodyB,
                Response = minPenetration * mtv,
                IsColliding = true
            });
        }