/// <summary>
        /// If objects are moving toward each other in x direction, returns weighted average of x velocities and original y velocities.
        /// <para>Repeats logic in y direction.</para>
        /// </summary>
        public static VelocityPair CollideSlide(BoxCollider left, BoxCollider right, Vector2 leftVel, Vector2 rightVel, float horzLeftWeight = 0.5f, float vertLeftWeight = 0.5f)
        {
            if (PhysicsMath.GetNormal(left, right).X != 0)
            {
                // Horizontal collision

                if (IsMovingTowardEachOther(left.Position.X, right.Position.X, leftVel.X, rightVel.X))
                {
                    // Objects are moving toward each other in x direction, return weighted average of x velocities.
                    float xAvg = WeightedAverage(leftVel.X, rightVel.X, horzLeftWeight);
                    return(new VelocityPair(new Vector2(xAvg, leftVel.Y), new Vector2(xAvg, rightVel.Y)));
                }
                else
                {
                    // Objects are moving apart, return original velocities.
                    return(new VelocityPair(leftVel, rightVel));
                }
            }
            else
            {
                // Vertical collision

                if (IsMovingTowardEachOther(left.Position.Y, right.Position.Y, leftVel.Y, rightVel.Y))
                {
                    // Objects are moving toward each other in y direction, return weighted average of y velocities.
                    float yAvg = WeightedAverage(leftVel.Y, rightVel.Y, vertLeftWeight);
                    return(new VelocityPair(new Vector2(leftVel.X, yAvg), new Vector2(rightVel.X, yAvg)));
                }
                else
                {
                    // Objects are moving apart, return original velocities.
                    return(new VelocityPair(leftVel, rightVel));
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Collides the given actor against all other rigidbodies and calculate the allowed velocity during this frame.
        /// </summary>
        /// <remarks>This function will immediately return if the calculated velocity becomes zero.</remarks>
        private static void CalculateActorVelocity(ActorRigidbody actor)
        {
            actor.ProcessingData.CalcVel = actor.Velocity;

            if (actor.Velocity == Vector2.Zero)
            {
                return;
            }


            foreach (var staticbody in AllStatics)
            {
                if (actor.ProcessingData.CalcVel == Vector2.Zero)
                {
                    return;
                }

                if (PhysicsMath.IsOverlapping(actor.MainCollider, staticbody.MainCollider))
                {
                    if (!PhysicsMath.IsSlidingCorner(actor.MainCollider, staticbody.MainCollider))
                    {
                        actor.ProcessingData.CalcVel = VelocityMath.IntoPlane(actor.ProcessingData.CalcVel, PhysicsMath.GetNormal(actor.MainCollider, staticbody.MainCollider));
                    }
                }
            }

            foreach (var solid in AllSolids)
            {
                foreach (var solidCollider in solid.Colliders)
                {
                    if (actor.ProcessingData.CalcVel == Vector2.Zero)
                    {
                        return;
                    }

                    if (PhysicsMath.IsOverlapping(actor.MainCollider, solidCollider))
                    {
                        if (!PhysicsMath.IsSlidingCorner(actor.MainCollider, solidCollider))
                        {
                            actor.ProcessingData.CalcVel = VelocityMath.IntoPlane(actor.ProcessingData.CalcVel, PhysicsMath.GetNormal(actor.MainCollider, solidCollider));
                        }
                    }
                }
            }
        }
Пример #3
0
        private static void CalculateSolidVelocity(SolidRigidbody solid)
        {
            solid.ProcessingData.CalcVel = solid.Velocity;

            if (solid.Velocity == Vector2.Zero)
            {
                return;                                             // Early exit if no velocity.
            }
            // Regional check against all static rigidbodies
            foreach (var staticbody in AllStatics)
            {
                foreach (var collider in solid.Colliders)
                {
                    if (solid.ProcessingData.CalcVel == Vector2.Zero)
                    {
                        return;
                    }

                    if (PhysicsMath.IsOverlapping(collider, staticbody.MainCollider))
                    {
                        if (!PhysicsMath.IsSlidingCorner(collider, staticbody.MainCollider))
                        {
                            solid.ProcessingData.CalcVel = VelocityMath.IntoPlane(solid.ProcessingData.CalcVel, PhysicsMath.GetNormal(collider, staticbody.MainCollider));

                            Console.WriteLine($"Solid collision against {staticbody.Entity} ({collider.LocalPosition}) to yield {solid.ProcessingData.CalcVel}");
                        }
                    }
                }
            }

            // Regional check against other solids
            foreach (var otherSolid in AllSolids)
            {
                if (solid.ProcessingData.CalcVel == Vector2.Zero)
                {
                    return;
                }

                // Skip self
                if (ReferenceEquals(solid, otherSolid))
                {
                    continue;
                }

                // Skip if other solid has already processed this solid
                if (otherSolid.ProcessingData.CheckedAgainst.Contains(solid))
                {
                    continue;
                }


                if (PhysicsMath.IsOverlapping(solid.MainCollider, otherSolid.MainCollider))
                {
                    if (!PhysicsMath.IsSlidingCorner(solid.MainCollider, otherSolid.MainCollider))
                    {
                        VelocityPair result = Ruleset.Get(solid, otherSolid);

                        Console.WriteLine($"Collided {solid.Entity} against {otherSolid.Entity} to yield {result.left} and {result.right}");

                        solid.ProcessingData.CalcVel      = result.left;
                        otherSolid.ProcessingData.CalcVel = result.right;

                        solid.ProcessingData.CheckedAgainst.Add(otherSolid);
                        otherSolid.ProcessingData.CheckedAgainst.Add(solid);
                    }
                }
            }
        }