示例#1
0
        public void HandlePhysicalCollision(CollisionSystem.Pair actor, CollisionComponent target, GameTime gameTime, bool swept) //TODO Implement Swept CC sometime
        {
            if (swept)
            {
                float entryTime = SweptAABB(actor, target, gameTime, out var normalX, out var normalY);
                if (entryTime <= 0 || entryTime >= 1)
                {
                    return;
                }
                MoveToEntry(actor, entryTime, gameTime);
                HandleCollisionResponseBehavior(actor, normalX, normalY);
                ApplyRemainingSpeed(actor, 1 - entryTime, gameTime);
            }
            else
            {
                if ((actor.Collision.IsPhasing || target.IsPhasing) && (!target.IsWall))
                {
                    return;
                }

                if (actor.Collision.CollisionRectangle.Intersects(target.CollisionRectangle))
                {
                    Vector2 penetrationVector = ClosestPointOnBoundsToPoint(CalculateMinkowskiDifference(actor.Collision.CollisionRectangle, target.CollisionRectangle), Vector2.Zero);
                    actor.Collision.CollisionRectangle -= penetrationVector;
                    Point normals = PenetrationToNormals(penetrationVector);
                    HandleCollisionResponseBehavior(actor, normals.X, normals.Y);
                }
            }

            AlignMovementWithCollision(actor);
        }
示例#2
0
 private static void BlockActor(CollisionSystem.Pair actor, int normalX, int normalY)
 {
     if (normalX != 0)
     {
         actor.Movement.Speed.ChangeX(0);
     }
     if (normalY != 0)
     {
         actor.Movement.Speed.ChangeY(0);
     }
 }
示例#3
0
 private void HandleCollisionResponseBehavior(CollisionSystem.Pair actor, int normalX, int normalY)
 {
     if (actor.Collision.Behavior == CollisionBehavior.Block)
     {
         BlockActor(actor, normalX, normalY);
     }
     else if (actor.Collision.Behavior == CollisionBehavior.Bounce)
     {
         BounceActor(actor, normalX, normalY);
     }
 }
示例#4
0
        private static float SweptAABB(CollisionSystem.Pair actor, CollisionComponent target, GameTime gameTime, out int normalX, out int normalY) //TODO THIS ALGORITHM IS NOT FUNCTIONAL, TOO LAZY TO FIX IT NOW
        {
            float xEntryDistance, yEntryDistance;
            float xExitDistance, yExitDistance;

            #region calculate distances
            if (actor.Movement.Speed.Cartesian.X > 0.0f)
            {
                xEntryDistance = target.CollisionRectangle.X - (actor.Collision.CollisionRectangle.X + actor.Collision.CollisionRectangle.Width);
                xExitDistance  = (target.CollisionRectangle.X + target.CollisionRectangle.Width) - actor.Collision.CollisionRectangle.X;
            }
            else
            {
                xEntryDistance = (target.CollisionRectangle.X + target.CollisionRectangle.Width) - actor.Collision.CollisionRectangle.X;
                xExitDistance  = target.CollisionRectangle.X - (actor.Collision.CollisionRectangle.X + actor.Collision.CollisionRectangle.Width);
            }

            if (actor.Movement.Speed.Cartesian.Y > 0.0f)
            {
                yEntryDistance = target.CollisionRectangle.Y - (actor.Collision.CollisionRectangle.Y + actor.Collision.CollisionRectangle.Height);
                yExitDistance  = (target.CollisionRectangle.Y + target.CollisionRectangle.Height) - actor.Collision.CollisionRectangle.Y;
            }
            else
            {
                yEntryDistance = (target.CollisionRectangle.Y + target.CollisionRectangle.Height) - actor.Collision.CollisionRectangle.Y;
                yExitDistance  = target.CollisionRectangle.Y - (actor.Collision.CollisionRectangle.Y + actor.Collision.CollisionRectangle.Height);
            }
            #endregion

            float xEntryTime, yEntryTime;
            float xExitTime, yExitTime;

            #region calculate entry and exit times
            if (actor.Movement.Speed.Cartesian.X == 0.0f)
            {
                xEntryTime = float.NegativeInfinity;
                xExitTime  = float.PositiveInfinity;
            }
            else
            {
                xEntryTime = xEntryDistance / (actor.Movement.Speed.Cartesian.X * (float)gameTime.ElapsedGameTime.TotalSeconds);
                xExitTime  = xExitDistance / (actor.Movement.Speed.Cartesian.Y * (float)gameTime.ElapsedGameTime.TotalSeconds);
            }

            if (actor.Movement.Speed.Cartesian.Y == 0.0f)
            {
                yEntryTime = float.NegativeInfinity;
                yExitTime  = float.PositiveInfinity;
            }
            else
            {
                yEntryTime = yEntryDistance / (actor.Movement.Speed.Cartesian.Y * (float)gameTime.ElapsedGameTime.TotalSeconds);
                yExitTime  = yExitDistance / (actor.Movement.Speed.Cartesian.Y * (float)gameTime.ElapsedGameTime.TotalSeconds);
            }
            #endregion
            if (xEntryTime > 1.0f)
            {
                xEntryTime = -float.MaxValue;
            }
            if (yEntryTime > 1.0f)
            {
                yEntryTime = -float.MaxValue;
            }
            float entryTime = Math.Max(xEntryTime, yEntryTime);
            float exitTime  = Math.Min(xExitTime, yExitTime);

            #region no collision happened
            if ((entryTime > exitTime) || (xEntryTime < 0.0f && yEntryTime < 0.0f))
            {
                normalX = 0;
                normalY = 0;
                return(1.0f);
            }

            #endregion

            #region set normals
            if (xEntryTime > yEntryTime)
            {
                normalX = -1;
                normalY = 1;
            }
            else
            {
                normalX = 1;
                normalY = -1;
            }
            #endregion
            return(entryTime);
        }
示例#5
0
 private static void BounceActor(CollisionSystem.Pair actor, int normalX, int normalY)
 {
     actor.Movement.Speed.ChangeX(actor.Movement.Speed.Cartesian.X * normalX);
     actor.Movement.Speed.ChangeY(actor.Movement.Speed.Cartesian.Y * normalY);
 }
示例#6
0
 private static void AlignMovementWithCollision(CollisionSystem.Pair pair)
 {
     pair.Movement.Position.X = pair.Collision.CollisionRectangle.Center.X;
     pair.Movement.Position.Y = pair.Collision.CollisionRectangle.Center.Y;
 }
示例#7
0
 private static void ApplyRemainingSpeed(CollisionSystem.Pair actor, float remainingTime, GameTime gameTime)
 {
     actor.Collision.CollisionRectangle.X += (int)(actor.Movement.Speed.Cartesian.X * (remainingTime * (float)gameTime.ElapsedGameTime.TotalSeconds));
     actor.Collision.CollisionRectangle.Y += (int)(actor.Movement.Speed.Cartesian.Y * (remainingTime * (float)gameTime.ElapsedGameTime.TotalSeconds));
 }
示例#8
0
 private static void MoveToEntry(CollisionSystem.Pair actor, float entryTime, GameTime gameTime)
 {
     actor.Collision.CollisionRectangle.X += (int)(actor.Movement.Speed.Cartesian.X * (entryTime * (float)gameTime.ElapsedGameTime.TotalSeconds));
     actor.Collision.CollisionRectangle.Y += (int)(actor.Movement.Speed.Cartesian.Y * (entryTime * (float)gameTime.ElapsedGameTime.TotalSeconds));
 }