Ejemplo n.º 1
0
        // Returns the clip collision that has resolution priority (or null if neither are colliding).
        private CollisionInfoNew GetPriorityCollision(Entity entity, CollisionInfoNew collision1, CollisionInfoNew collision2)
        {
            if (!collision1.IsCollidingAndNotAllowedClipping && !collision2.IsCollidingAndNotAllowedClipping)
                return null;
            else if (collision1.IsCollidingAndNotAllowedClipping && !collision2.IsCollidingAndNotAllowedClipping)
                return collision1;
            else if (collision2.IsCollidingAndNotAllowedClipping && !collision1.IsCollidingAndNotAllowedClipping)
                return collision2;

            // Resolvable collisions over non resolvable collisions.
            if (collision1.IsResolvable && !collision2.IsResolvable)
                return collision1;
            else if (collision2.IsResolvable && !collision1.IsResolvable)
                return collision2;

            // Dynamic collisions over static collisions.
            if (IsSolidObjectDynamic(collision1.CollidedObject) && !IsSolidObjectDynamic(collision2.CollidedObject))
                return collision1;
            if (IsSolidObjectDynamic(collision2.CollidedObject) && !IsSolidObjectDynamic(collision1.CollidedObject))
                return collision2;

            Tile tile1 = collision1.CollidedObject as Tile;
            Tile tile2 = collision2.CollidedObject as Tile;
            Entity entity1 = collision1.CollidedObject as Entity;
            Entity entity2 = collision2.CollidedObject as Entity;

            // Entities over tiles.
            if (entity1 != null && tile2 != null)
                return collision1;
            if (entity2 != null && tile1 != null)
                return collision2;

            // Compare two entities.
            if (entity1 != null && entity2 != null) {
                if (entity1.EntityIndex < entity2.EntityIndex)
                    return collision1;
                if (entity2.EntityIndex < entity1.EntityIndex)
                    return collision2;
            }

            // Compare two tiles.
            if (tile1 != null && tile2 != null) {
                if (tile1.Position.Y > tile2.Position.Y)
                    return collision1;
                else if (tile2.Position.Y > tile1.Position.Y)
                    return collision2;
                else if (tile1.Position.X > tile2.Position.X)
                    return collision1;
                else if (tile2.Position.X > tile1.Position.X)
                    return collision2;
                else if (tile1.Layer > tile2.Layer)
                    return collision1;
                else if (tile2.Layer > tile1.Layer)
                    return collision2;
            }

            return collision1;
        }
Ejemplo n.º 2
0
 // Get the positional correction needed to resolve a collision.
 private Vector2F GetPositionalCorrection(CollisionInfoNew collision)
 {
     float resolveDistance = Math.Max(0.0f, collision.PenetrationDistance - collision.MaxAllowedPenetrationDistance);
     return -Directions.ToVector(collision.PenetrationDirection) * resolveDistance;
 }
Ejemplo n.º 3
0
        // Returns true if the given collision needs resolution.
        private bool CanResolveCollision(Entity entity, CollisionInfoNew collision)
        {
            if (!collision.IsColliding || collision.IsAllowedClipping)
                return false;

            // Don't resolve collisions if they are within the allowable edge clip amount.
            if (IsSafeClipping(entity, 1 - Directions.ToAxis(collision.PenetrationDirection), entity.Physics.PositionedCollisionBox, collision.CollidedObject, collision.CollisionBox))
                return false;

            // Static collisions cannot resolve into colliding with other static objects.
            Tile tile = collision.CollidedObject as Tile;
            if (tile != null && !tile.IsInMotion) {
                Vector2F newPosition = entity.Position + GetPositionalCorrection(collision);
                if (IsCollidingAt(entity, newPosition, true))
                    return false;
            }

            if ((collision.CollidedObject is Tile) && !entity.Physics.CollideWithWorld)
                return false;
            if ((collision.CollidedObject is Entity) && !entity.Physics.CollideWithEntities)
                return false;

            return true;
        }
Ejemplo n.º 4
0
 // Returns true if the given clip collision needs resolution.
 private bool CanResolveCollisionPair(Entity entity, CollisionInfoNew collision1, CollisionInfoNew collision2)
 {
     // Static collisions cannot resolve into colliding with other static objects.
     Tile tile1 = collision1.CollidedObject as Tile;
     Tile tile2 = collision2.CollidedObject as Tile;
     if ((tile1 != null && !tile1.IsInMotion) || (tile2 != null && !tile2.IsInMotion)) {
         Vector2F newPosition = entity.Position;
         newPosition += GetPositionalCorrection(collision1);
         newPosition += GetPositionalCorrection(collision2);
         if (IsCollidingAt(entity, newPosition, true))
             return false;
     }
     return true;
 }
Ejemplo n.º 5
0
        // Resolve clip collisions.
        private void ResolveClipCollisions(Entity entity)
        {
            // Determine which collisions have priority.
            CollisionInfoNew[] collisions = new CollisionInfoNew[2];
            collisions[Axes.X] = GetPriorityCollision(entity,
                entity.Physics.ClipCollisionInfo[Directions.Right],
                entity.Physics.ClipCollisionInfo[Directions.Left]);
            collisions[Axes.Y] = GetPriorityCollision(entity,
                entity.Physics.ClipCollisionInfo[Directions.Up],
                entity.Physics.ClipCollisionInfo[Directions.Down]);

            for (int i = 0; i < 2; i++) {
                CollisionInfoNew collision = collisions[i];
                if (collision != null && collision.IsResolvable) {
                    // Resolve the collision.
                    entity.Position += GetPositionalCorrection(collision);
                    collision.IsResolved = true;

                    // Add to the penetration distance of the opposite collision.
                    CollisionInfoNew otherCollision = entity.Physics.ClipCollisionInfo[Directions.Reverse(collision.PenetrationDirection)];
                    float resolveDistance = Math.Max(0.0f, collision.PenetrationDistance - collision.MaxAllowedPenetrationDistance);
                    otherCollision.PenetrationDistance += resolveDistance;
                }
            }

            // Check if the collisions can be only resolved together and NOT separately.
            if (collisions[0] != null && collisions[1] != null &&
                !collisions[0].IsResolvable && !collisions[1].IsResolvable &&
                CanResolveCollisionPair(entity, collisions[0], collisions[1]))
            {
                for (int i = 0; i < 2; i++) {
                    CollisionInfoNew collision = collisions[i];
                    // Resolve the collision.
                    entity.Position += GetPositionalCorrection(collision);
                    collision.IsResolved = true;

                    // Add to the penetration distance of the opposite collision.
                    CollisionInfoNew otherCollision = entity.Physics.ClipCollisionInfo[Directions.Reverse(collision.PenetrationDirection)];
                    float resolveDistance = Math.Max(0.0f, collision.PenetrationDistance - collision.MaxAllowedPenetrationDistance);
                    otherCollision.PenetrationDistance += resolveDistance;
                }
            }
        }