//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;
            }
        }
        //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);
                 }
             }
         }
     }
 }
 public override void Update(GameTime gameTime)
 {
     foreach (Box aabb in boxes.Values)
     {
         if (aabb is KineticBox)
         {
             KineticBox box = aabb as KineticBox;
             box.UpdateSpeed(gameTime);
             box.Update(gameTime);
             box.UpdateLocation(gameTime);
             CollisionHelper.StopSpeed(box, SpatialGrid);
         }
         else
         {
             aabb.Update(gameTime);
         }
     }
 }
        public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = Game.Services.GetService <SpriteBatch>();

            foreach (Box aabb in SpatialGrid.GetProbableCollisions(new Box(null, 0, 0, Width, Height)))
            {
                if (aabb.CollisionSide.HasFlag(Box.CollisionDirection.Inside))
                {
                    DrawHelper.DrawRectangle(spriteBatch, aabb.Rectangle, new Color(Color.Green, 0.1f));
                }
                DrawHelper.DrawOutline(spriteBatch, aabb.Rectangle, Color.Black);
                if (aabb.CollisionSide.HasFlag(Box.CollisionDirection.Top))
                {
                    DrawHelper.DrawRectangle(spriteBatch, new Rectangle(aabb.Rectangle.Left, aabb.Rectangle.Top, aabb.Rectangle.Width, 1), Color.Green);
                }
                if (aabb.CollisionSide.HasFlag(Box.CollisionDirection.Left))
                {
                    DrawHelper.DrawRectangle(spriteBatch, new Rectangle(aabb.Rectangle.Left, aabb.Rectangle.Top, 1, aabb.Rectangle.Height), Color.Green);
                }
                if (aabb.CollisionSide.HasFlag(Box.CollisionDirection.Right))
                {
                    DrawHelper.DrawRectangle(spriteBatch, new Rectangle(aabb.Rectangle.Right - 1, aabb.Rectangle.Top, 1, aabb.Rectangle.Height), Color.Green);
                }
                if (aabb.CollisionSide.HasFlag(Box.CollisionDirection.Bottom))
                {
                    DrawHelper.DrawRectangle(spriteBatch, new Rectangle(aabb.Rectangle.Left, aabb.Rectangle.Bottom - 1, aabb.Rectangle.Width, 1), Color.Green);
                }

                if (aabb is KineticBox)
                {
                    KineticBox box = aabb as KineticBox;

                    Vector2 end = box.Acceleration;
                    end *= (float)gameTime.ElapsedGameTime.TotalSeconds;
                    DrawHelper.DrawLine(spriteBatch, box.Rectangle.Center, box.Rectangle.Center + end.ToPoint(), Color.Red);

                    end  = box.Speed;
                    end *= (float)gameTime.ElapsedGameTime.TotalSeconds;
                    DrawHelper.DrawLine(spriteBatch, box.Rectangle.Center, box.Rectangle.Center + end.ToPoint(), Color.Blue);
                }
            }
            SpatialGrid.Draw(gameTime);
        }
        //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);
        }
        private void aabb_PropertyChanged(Box sender, PropertyChangedEventArgs e)
        {
            SpatialGrid.Add(sender);

            if (sender is KineticBox)
            {
                KineticBox box = sender as KineticBox;
                if (box.SpeedUpdate)
                {
                    CollisionHelper.MovementCollision(box, SpatialGrid);
                }
                else
                {
                    CollisionHelper.ClassicCollision(box, SpatialGrid);
                }
            }
            else
            {
                CollisionHelper.ExpulseCollision(sender, SpatialGrid);
            }

            CollisionHelper.SetCollisionNotification(sender, SpatialGrid);
        }
Пример #9
0
 public KineticBox(KineticBox box)
     : this(box.Game, box.X, box.Y, box.Width, box.Height, box.Solid, box.InteractWithSolid, box.MovementIncrement)
 {
 }