//private static Vector2 ExitVector(Box collision, Box collisionWith)
        //{
        //	Box intersection = Box.Intersect(collision, collisionWith);
        //	Vector2 intersectionVector = new Vector2(intersection.Width, intersection.Height);
        //	Vector2 directionVector = collision.Center - collisionWith.Center;
        //
        //	if (directionVector == Vector2.Zero)
        //	{
        //		directionVector.X = -1;
        //	}
        //
        //	Vector2 exitVector = intersectionVector * (directionVector / directionVector.Length());
        //
        //	if ((exitVector.Y != 0) && (Math.Abs(exitVector.X) > Math.Abs(exitVector.Y)))
        //	{
        //		exitVector.X = 0;
        //	}
        //	else if ((exitVector.X != 0) && (Math.Abs(exitVector.Y) > Math.Abs(exitVector.X)))
        //	{
        //		exitVector.Y = 0;
        //	}
        //
        //	return exitVector;
        //}

        public static void MovementCollision(KineticBox box, SpatialGrid spatialGrid)
        {
            //S'il y a vraiment collision
            if (Intersect(box, spatialGrid.GetProbableSolidCollisions(box)))
            {
                Vector2 exitVector = box.OldLocation - box.Location;

                KineticBox copy = ResolveMovementCollision(box, exitVector, spatialGrid);

                Vector2           finalMovement = box.Location - copy.Location;
                IEnumerable <Box> solids        = spatialGrid.GetProbableSolidCollisions(copy);
                if (((finalMovement.X < 0) && (LeftCollision(copy, solids))) ||
                    ((finalMovement.X > 0) && ((RightCollision(copy, solids)))))
                {
                    finalMovement.X = 0;
                }
                if (((finalMovement.Y < 0) && (TopCollision(copy, solids))) ||
                    ((finalMovement.Y > 0) && (BottomCollision(copy, solids))))
                {
                    finalMovement.Y = 0;
                }

                if (finalMovement != Vector2.Zero)
                {
                    copy.Offset(finalMovement);
                    MovementCollision(copy, spatialGrid);
                }
                else
                {
                    box.Speed = Vector2.Zero;
                }

                box.Location = copy.Location;
            }
        }
 public PhysicsEngine(Game game, int width, int height)
     : base(game)
 {
     boxes       = new SortedList <int, Box>(new DuplicateKeyComparer <int>());
     SpatialGrid = new SpatialGrid(Game, (int)Math.Ceiling((double)width / SpatialGrid.TILE_SIZE), (int)Math.Ceiling((double)height / SpatialGrid.TILE_SIZE));
     DrawOrder   = int.MaxValue;
 }
        public static void SetCollisionNotification(Box sender, SpatialGrid spatialGrid)
        {
            Box copy = new Box(sender);

            copy.Inflate(1, 1);
            foreach (Box aabb in spatialGrid.GetProbableCollisions(sender))
            {
                if (aabb.Intersects(copy))
                {
                    sender.CollisionNotification(aabb);
                }
            }
            copy.Inflate(-1, -1);
        }
        //C'est sacré
        public static void StopSpeed(KineticBox box, SpatialGrid spatialGrid)
        {
            //Restore l'ancienne vitesse en vérifiant quels côtés ont fait la collision
            IEnumerable <Box> solids = spatialGrid.GetProbableSolidCollisions(box);

            if (((box.Speed.X <= 0) && (LeftCollision(box, solids))) ||
                ((box.Speed.X >= 0) && ((RightCollision(box, solids)))))
            {
                box.Speed.X = 0;
            }
            if (((box.Speed.Y <= 0) && (TopCollision(box, solids))) ||
                ((box.Speed.Y >= 0) && (BottomCollision(box, solids))))
            {
                box.Speed.Y = 0;
            }
        }
 public static void ExpulseCollision(Box sender, SpatialGrid spatialGrid)
 {
     if (sender.Solid)
     {
         foreach (Box aabb in spatialGrid.GetProbableCollisions(sender))
         {
             if (aabb is KineticBox)
             {
                 KineticBox box = aabb as KineticBox;
                 if ((box.InteractWithSolid) && (box.Intersects(sender)))
                 {
                     ClassicCollision(box, spatialGrid);
                 }
             }
         }
     }
 }
        //Use with caution
        public static void ClassicCollision(KineticBox sender, SpatialGrid spatialGrid)
        {
            if (sender.InteractWithSolid)
            {
                Vector2 exitVector = Vector2.Zero;

                int total = 1;
                foreach (Box collision in spatialGrid.GetProbableSolidCollisions(sender))
                {
                    if (collision.Intersects(sender))
                    {
                        exitVector += sender.ExitVector(collision);
                        total++;
                    }
                }
                if (exitVector != Vector2.Zero)
                {
                    exitVector /= total;
                    sender.Offset(exitVector);
                }
            }
        }
        private static KineticBox ResolveMovementCollision(KineticBox box, Vector2 exitVector, SpatialGrid spatialGrid)
        {
            KineticBox copy = new KineticBox(box);

            //Tant que la collision n'est pas résolue
            while (copy.Location != copy.OldLocation)             //Pourrait être optimisé contre une perte de précision?
            {
                if (Intersect(copy, spatialGrid.GetProbableSolidCollisions(copy)))
                {
                    //Défait le mouvement qui créer la collion
                    copy.Offset(exitVector);
                }
                else
                {
                    //Avance plus lentement vers la collion
                    exitVector /= 2;
                    copy.Offset(-exitVector);
                }
            }

            return(copy);
        }