예제 #1
0
 /// <summary>
 /// Constructor for a force instance.
 /// </summary>
 /// <param name="body">The target body.</param>
 /// <param name="force">The velocity of the force.</param>
 public Force(Body body, Vector3 force)
     : this()
 {
     // Set the variables.
     Body = body;
     Velocity = force;
 }
예제 #2
0
 /// <summary>
 /// Add a body with which this body has collided with.
 /// </summary>
 /// <param name="body">The body with which a collisions has occurred.</param>
 public void AddCollision(Body body)
 {
     _Collisions.Add(body);
 }
예제 #3
0
        /// <summary>
        /// Calculate the impact force by using the kinetic energy.
        /// </summary>
        /// <param name="b1">The first body to check.</param>
        /// <param name="b2">The second body to check.</param>
        /// <returns>The impact force between the two bodies.</returns>
        private Force ImpactForceEnergy(Body b1, Body b2)
        {
            // Calculate the Kinetic Energy of the two bodies.
            Vector3 energyB1 = Calculator.Absolute(b1.Velocity * b1.Velocity) * b1.Mass / 2;
            Vector3 energyB2 = Calculator.Absolute(b2.Velocity * b2.Velocity) * b2.Mass / 2;

            // Get the intersection rectangle.
            Rectangle intersection = b1.Shape.GetIntersection(b2.Shape);
            // Calculate the Collision point.
            Vector2 collision = Calculator.ToCentroid(intersection);

            // The average kinetic energy. Multiply with something to lower the
            // collision force.
            Vector3 averageEnergy = ((energyB1 + energyB2) / 2) * _EnergyDecrease;

            // Multiply the Average Kinetic Energy with the collision vector
            // direction relative to the body's position.
            Vector3 impact = averageEnergy * new Vector3(Calculator.Direction(Calculator.GetAngle(collision, b1.LayeredPosition)), 0);

            // Return the average vector.
            return new Force(b1, impact);
        }
예제 #4
0
        /// <summary>
        /// Check for collisions between two bodies at a certain range of z-coordinates (height).
        /// </summary>
        /// <param name="b1">The first body to check.</param>
        /// <param name="b2">The second body to check.</param>
        /// <param name="mtv">The MTV of the layered collision.</param>
        /// <returns>The MTV of the intersection.</returns>
        private CollisionData GetLayeredCollision(Body b1, Body b2, CollisionData mtv)
        {
            // If there is no layered collision between the bodies, stop here.
            if (!mtv.HasCollision) { return mtv; }

            // Get the dynamic and static body.
            Body a = b1.IsStatic ? b2 : b1;
            Body b = (a == b1) ? b2 : b1;

            // Get the min and max heights for both bodies.
            Vector2 h1 = new Vector2(a.Shape.BottomDepth, a.Shape.GetTopDepth(a.LayeredPosition));
            Vector2 h2 = new Vector2(b.Shape.BottomDepth, b.Shape.GetTopDepth(a.LayeredPosition));

            // Get min and max heights for possible collisions between the bodies.
            Vector2 heights = Calculator.GetMiddleValues(h1, h2);

            // If there were no matching heights found, no collision possible.
            if ((heights.X < 0 && heights.Y > 0) || (h2.Y - h1.X) < 3) { return mtv; }

            //A collision has been found.
            mtv.HasCollision = true;

            // Return the MTV.
            return mtv;
        }
예제 #5
0
        /// <summary>
        /// Calculate the impact force vector.
        /// </summary>
        /// <param name="b1">The first body to check.</param>
        /// <param name="b2">The second body to check.</param>
        /// <returns>The impact force vector.</returns>
        private Force ImpactForce(Body b1, Body b2)
        {
            // Calculate the Energy of the two bodies before impact.
            Vector3 energyB1 = Calculator.Absolute(b1.Velocity * b1.Mass);
            Vector3 energyB2 = Calculator.Absolute(b2.Velocity * b2.Mass);
            Vector3 energyBT = energyB1 + energyB2;

            // Get the intersection rectangle.
            Rectangle intersection = b1.Shape.GetIntersection(b2.Shape);
            // Calculate the Collision point.
            Vector2 collision = Calculator.ToCentroid(intersection);

            // The mass ratio between the objects.
            float massRatio = b2.Mass / b1.Mass;

            // The average kinetic energy. Multiply with something to lower the collision force and also with the mass ratio.
            Vector3 averageEnergy = (energyBT / 2) * _EnergyDecrease * massRatio;

            // Multiply the Average kinetic Energy with the collision vector direction relative to the body's position.
            Vector3 impact = averageEnergy * new Vector3(Calculator.Direction(Calculator.GetAngle(collision, b1.LayeredPosition)), 0);

            // Return the average vector.
            return new Force(b1, impact);
        }
예제 #6
0
        /// <summary>
        /// Pull two bodies that are intersecting apart by using the MTV.
        /// </summary>
        /// <param name="b1">The first body to check.</param>
        /// <param name="b2">The second body to check.</param>
        /// <param name="mtv">The MTV of the collision.</param>
        private void ClearIntersection(Body b1, Body b2, CollisionData mtv)
        {
            // If the MTV is null, stop here.
            if (!mtv.HasCollision) { return; }

            // Add the MTV to the first body and subtract it from the second. Only move dynamic bodies!
            if (!b1.IsStatic)
            {
                b1.Shape.LayeredPosition = b1.Shape.LayeredPosition + mtv.Axis * mtv.Overlap;
                b1.Velocity = Vector3.Zero;
            }
            if (!b2.IsStatic)
            {
                b2.Shape.LayeredPosition = b2.Shape.LayeredPosition - mtv.Axis * mtv.Overlap;
                b2.Velocity = Vector3.Zero;
            }
        }
예제 #7
0
 /// <summary>
 /// Calculate the friction force and its direction for a body.
 /// </summary>
 /// <param name="b">The body to calculate the friction for.</param>
 /// <returns>The friction.</returns>
 private Force GetBodyFriction(Body b)
 {
     // First, multiply the friction coefficient with the gravity's force exertion on the body (mass * gravity value),
     // then with the direction of the velocity. Inverse the vector and finally return the result.
     // return (new Force(b, Vector.multiply(Vector.getDirection(Vector.getAngle(b.position, b.velocity)), b.frictionCoefficient * (b.mass * gravity))));
     return new Force(b, Vector3.Negate(Calculator.Direction(b.Velocity, Vector3.Distance(Calculator.Absolute(b.Velocity), Vector3.Zero))) *
             (b.FrictionCoefficient * b.Mass * _Gravity));
 }
예제 #8
0
        /// <summary>
        /// Do a broad phase collision check. (Currently checks if the bodies might intersect on the XY-axis.
        /// </summary>
        /// <param name="b1">The first body to check.</param>
        /// <param name="b2">The second body to check.</param>
        /// <returns>Whether two bodies are close enough for a collision.</returns>
        private bool BroadPhase(Body b1, Body b2)
        {
            // Try this.
            try
            {
                // Check if the bodies are within range.
                return Vector2.Distance(b1.LayeredPosition, b2.LayeredPosition) < (Math.Max(b1.Shape.Width, b1.Shape.Height) + Math.Max(b2
                        .Shape.Width, b2.Shape.Height));
            }
            // Catch the exception and display relevant information.
            catch (Exception e)
            {
                Console.WriteLine(this + ": Broad Phase Error. (" + e + ") - Body1: " + b1 + " Body2: " + b2);
            }

            // Something went wrong.
            return false;
        }
예제 #9
0
        /// <summary>
        /// Check for collision between two bodies where one is coming from above the other.
        /// This is a preemptive step due to the use of body velocity to project future positions.
        /// </summary>
        /// <param name="b1">The first body to check.</param>
        /// <param name="b2">The second body to check.</param>
        /// <param name="mtv">The MTV of the collision.</param>
        /// <returns>Whether there was a ground collision or not, from the first body's perspective</returns>
        private bool CheckGroundCollision(Body b1, Body b2, CollisionData mtv)
        {
            // The first body has to be dynamic or if there is no layered collision between the bodies, stop here.
            if (!mtv.HasCollision) { return false; }

            // Get the dynamic and static body.
            Body a = b1.IsStatic ? b2 : b1;
            Body b = (a == b1) ? b2 : b1;

            // Both bodies' depth positions.
            Vector2 h1 = new Vector2(a.Shape.BottomDepth, a.Shape.TopDepth);
            Vector2 h2 = new Vector2(b.Shape.BottomDepth, b.Shape.GetTopDepth(a.LayeredPosition));

            // The difference in height.
            double diff = h1.X - h2.Y;

            // If the distance between the bodies is either greater than the threshold or less than the velocity needed to collide, no collision.
            if (diff > Math.Max(-a.Velocity.Z + _Gravity, 0) || (h2.Y - h1.X) > 2) { return false; }

            // There must be a ground collision after all.
            return true;
        }
예제 #10
0
 /// <summary>
 /// Remove a body from the physics simulator.
 /// </summary>
 /// <param name="body">The body to remove.</param>
 public void RemoveBody(Body body)
 {
     _Bodies.Remove(body);
 }
예제 #11
0
        /// <summary>
        /// Get the forces connected to a certain body.
        /// </summary>
        /// <param name="body">The body used to find connected forces.</param>
        /// <returns>The connected forces.</returns>
        public List<Force> GetForces(Body body)
        {
            // Create the return variable.
            List<Force> force = new List<Force>();

            // Try this.
            try
            {
                // Loop through the forces array.
                foreach (Force f in _Forces)
                {
                    // Try to match the bodies in the Force.
                    if (f.Body == body) { force.Add(f); }
                }
            }
            // Catch the exception.
            catch (Exception e) { Console.WriteLine(this + ": Force Exists Error. (" + e + ")"); }

            // Return all forces belonging to a body.
            return force;
        }
예제 #12
0
        /// <summary>
        /// Check if the physics simulator contains a body.
        /// </summary>
        /// <param name="body">The body to look for.</param>
        /// <returns>Whether the body do indeed exist in the physics simulator.</returns>
        public bool Contains(Body body)
        {
            // Create the return variable.
            bool exists = false;

            // Try this.
            try
            {
                // Loop through the body array.
                foreach (Body b in _Bodies)
                {
                    // Try to match the bodies.
                    if (body == b) { exists = true; }
                }
            }
            // Catch the exception.
            catch (Exception e) { Console.WriteLine(this + ": Body Exists Error. (" + e + ")"); }

            // Return the result.
            return exists;
        }
예제 #13
0
 /// <summary>
 /// Add a body to the physics simulator.
 /// </summary>
 /// <param name="body">The body to add.</param>
 public void AddBody(Body body)
 {
     // Try to add the body at the end of the array.
     try
     {
         // If the body isn't already in the folds of the physics simulator.
         if (!_Bodies.Contains(body))
         {
             _Bodies.Add(body);
             body.PhysicsSimulator = this;
         }
     }
     // Catch the exception and display relevant information.
     catch (Exception e)
     {
         Console.WriteLine(this + ": Error adding body. (" + e + ")");
     }
 }
예제 #14
0
 /// <summary>
 /// Initialize the scene.
 /// </summary>
 /// <param name="scene">The scene this entity is part of.</param>
 protected virtual void Initialize(Scene scene)
 {
     // Initialize the variables.
     _Name = "";
     _Scene = scene;
     _Sprites = new SpriteManager();
     _Body = new Body(_Scene != null ? _Scene.PhysicsSimulator : null);
     _Body.Entity = this;
     _Body.AddBody();
 }