コード例 #1
0
ファイル: MainWindow.xaml.cs プロジェクト: ezszoftver/Physics
        private void glControl_Load(object sender, EventArgs e)
        {
            glControl.MakeCurrent();
            GL.Enable(EnableCap.DepthTest);
            GL.Disable(EnableCap.Lighting);
            GL.Disable(EnableCap.Texture2D);
            GL.Disable(EnableCap.CullFace);
            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            GL.ClearColor(0.5f, 0.5f, 1.0f, 1.0f);

            plane     = new Physics.Plane(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0, 1, 0));
            rigidBody = new RigidBody();

            rigidBody.m_fMass           = 1.0f;
            rigidBody.m_v3Position      = new Vector3(0, 6.0f, 0);
            rigidBody.m_fGravity        = new Vector3(0, -9.81f, 0);
            rigidBody.m_fRestitution    = 0.0f;
            rigidBody.m_fFriction       = 1.0f;
            rigidBody.m_fLinearDamping  = 0.5f;
            rigidBody.m_fAngularDamping = 0.5f;
            rigidBody.m_v3Rotate        = new Vector3(ToRadian(30.0f), 0, ToRadian(20.0f));

            rigidBody.m_listPoints.Add(new Vector3(-2.0f, -1.0f, -1.5f));
            rigidBody.m_listPoints.Add(new Vector3(+2.0f, -1.0f, -1.5f));
            rigidBody.m_listPoints.Add(new Vector3(-2.0f, +1.0f, -1.5f));
            rigidBody.m_listPoints.Add(new Vector3(+2.0f, +1.0f, -1.5f));
            rigidBody.m_listPoints.Add(new Vector3(-2.0f, -1.0f, +1.5f));
            rigidBody.m_listPoints.Add(new Vector3(+2.0f, -1.0f, +1.5f));
            rigidBody.m_listPoints.Add(new Vector3(-2.0f, +1.0f, +1.5f));
            rigidBody.m_listPoints.Add(new Vector3(+2.0f, +1.0f, +1.5f));

            // back
            rigidBody.m_listIndices.AddRange(new int[] { 3, 1, 0 });
            rigidBody.m_listIndices.AddRange(new int[] { 0, 2, 3 });
            // front
            rigidBody.m_listIndices.AddRange(new int[] { 4, 5, 7 });
            rigidBody.m_listIndices.AddRange(new int[] { 7, 6, 4 });
            // left
            rigidBody.m_listIndices.AddRange(new int[] { 6, 2, 0 });
            rigidBody.m_listIndices.AddRange(new int[] { 0, 4, 6 });
            // right
            rigidBody.m_listIndices.AddRange(new int[] { 1, 3, 7 });
            rigidBody.m_listIndices.AddRange(new int[] { 7, 5, 1 });
            // bottom
            rigidBody.m_listIndices.AddRange(new int[] { 0, 1, 5 });
            rigidBody.m_listIndices.AddRange(new int[] { 5, 4, 0 });
            // top
            rigidBody.m_listIndices.AddRange(new int[] { 7, 3, 2 });
            rigidBody.m_listIndices.AddRange(new int[] { 2, 6, 7 });

            rigidBody.Create();

            DispatcherTimer timer = new DispatcherTimer();

            timer.Tick    += Timer_Tick;
            timer.Interval = TimeSpan.FromSeconds(0);
            timer.Start();
        }
コード例 #2
0
ファイル: Explosion.cs プロジェクト: Selinux24/xnatanksgame
        /// <summary>
        /// Calcula la fuerza y la aplica al cuerpo especificado
        /// </summary>
        /// <param name="body">Cuerpo</param>
        /// <param name="duration">Duración</param>
        public override void UpdateForce(ref RigidBody body, float duration)
        {
            // Detectar la fase de la explosión en la que estamos
            if (m_TimePassed <= ImplosionDuration)
            {
                // Fase de implosión

                float distance = Vector3.Distance(body.Position, this.DetonationCenter);
                if (distance > this.ImplosionMinRadius && distance <= this.ImplosionMaxRadius)
                {
                    // El cuerpo está en el área de implosión. Aplicar las fuerzas
                    float max            = this.ImplosionMaxRadius - this.ImplosionMinRadius;
                    float curr           = distance - this.ImplosionMinRadius;
                    float forceMagnitude = curr / max;

                    Vector3 force = Vector3.Normalize(this.DetonationCenter - body.Position) * this.ImplosionForce * forceMagnitude;

                    body.AddForce(force);
                }
            }
            else if (m_TimePassed <= (ImplosionDuration + ConcussionDuration))
            {
                // Honda expansiva

                // Intervalo actual de máxima acción de la honda
                float min = this.ShockwaveSpeed * m_TimePassed;
                float max = this.ShockwaveSpeed * (m_TimePassed + duration);

                // Distancia al centro del objeto
                float distance = Vector3.Distance(body.Position, this.DetonationCenter);

                float totalDuration = this.ConcussionDuration + this.ImplosionDuration;
                float maxDuration   = this.ConcussionDuration;
                float maxDistance   = (this.ShockwaveSpeed * maxDuration) + this.ShockwaveThickness;

                float forceMagnitude = 0f;
                if (distance >= min && distance <= max)
                {
                    // En plena honda expansiva. Se aplican las fuerzas atenuadas sólo por la duración
                    float relativeTime = 0f;
                    if (m_TimePassed < totalDuration)
                    {
                        relativeTime = 1f - (m_TimePassed / totalDuration);
                    }

                    forceMagnitude = this.PeakConcussionForce * relativeTime;
                }
                else if (distance < min)
                {
                    // El objeto ha sido sobrepasado por la honda expansiva. Fuerza mínimamente atenuada
                    float relativeTime = 0f;
                    if (m_TimePassed < totalDuration)
                    {
                        relativeTime = 1f - (m_TimePassed / totalDuration);
                    }

                    forceMagnitude = this.PeakConcussionForce * relativeTime;
                }
                else if (distance > max && distance <= maxDistance)
                {
                    // El objeto no ha sido alcanzado por la honda expansiva. Fuerza atenuada por el tiempo y la distancia
                    float relativeDistance = 0f;
                    if (distance < maxDistance)
                    {
                        relativeDistance = 1f - (distance / maxDistance);
                    }

                    float relativeTime = 0f;
                    if (m_TimePassed < totalDuration)
                    {
                        relativeTime = 1f - (m_TimePassed / totalDuration);
                    }

                    forceMagnitude = this.PeakConcussionForce * relativeDistance * relativeTime;
                }

                if (forceMagnitude > 0f)
                {
                    Vector3 force = Vector3.Normalize(body.Position - this.DetonationCenter) * forceMagnitude;

                    body.AddForce(force);
                }
            }
            else
            {
                // Fin de la explosión
                m_ExplosionActive = false;
            }

            m_TimePassed += duration;
        }
コード例 #3
0
        private void glControl_Load(object sender, EventArgs e)
        {
            glControl.MakeCurrent();
            GL.Enable(EnableCap.DepthTest);
            GL.Disable(EnableCap.Lighting);
            GL.Disable(EnableCap.Texture2D);
            GL.Disable(EnableCap.CullFace);
            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            GL.ClearColor(0.5f, 0.5f, 1.0f, 1.0f);

            plane      = new Physics.Plane(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0, 1, 0));
            rigidBody1 = new RigidBody();

            loader = new OBJLoader();
            loader.LoadFromFile("", "henger.obj");

            Vector3 v3Gravity = new Vector3(0, -9.81f, 0);

            rigidBody1.m_fMass           = 1.0f;
            rigidBody1.m_v3Position      = new Vector3(0f, 5.0f, 0);
            rigidBody1.m_fGravity        = v3Gravity;
            rigidBody1.m_fRestitution    = 0.0f;
            rigidBody1.m_fFriction       = 1.0f;
            rigidBody1.m_v3Rotate        = new Vector3(ToRadian(0.0f), 0, ToRadian(60.0f));
            rigidBody1.m_fLinearDamping  = 0.2f;
            rigidBody1.m_fAngularDamping = 0.2f;

            float scale = 0.1f;

            foreach (Vector3 v in loader.vertices)
            {
                rigidBody1.m_listPoints.Add(new Vector3(v.X * scale, v.Y * scale, v.Z * scale));
            }

            foreach (OBJLoader.Material mat in loader.materials)
            {
                for (int i = 0; i < mat.indices.Count; i += 3)
                {
                    int i0 = mat.indices[i + 0].id_vertex;
                    int i1 = mat.indices[i + 1].id_vertex;
                    int i2 = mat.indices[i + 2].id_vertex;

                    rigidBody1.m_listIndices.AddRange(new int[] { i0, i1, i2 });
                }
            }

            rigidBody1.Create();

            loader = new OBJLoader();
            loader.LoadFromFile("", "sphere.obj");

            rigidBody2 = new RigidBody();

            rigidBody2.m_fMass           = 1.0f;
            rigidBody2.m_v3Position      = new Vector3(2f, 10.0f, 2);
            rigidBody2.m_fGravity        = v3Gravity;
            rigidBody2.m_fRestitution    = 0.0f;
            rigidBody2.m_fFriction       = 1.0f;
            rigidBody2.m_v3Rotate        = new Vector3(ToRadian(0.0f), 0, ToRadian(-15.0f));
            rigidBody2.m_fLinearDamping  = 0.2f;
            rigidBody2.m_fAngularDamping = 0.2f;

            foreach (Vector3 v in loader.vertices)
            {
                rigidBody2.m_listPoints.Add(new Vector3(v.X * scale, v.Y * scale, v.Z * scale));
            }

            foreach (OBJLoader.Material mat in loader.materials)
            {
                for (int i = 0; i < mat.indices.Count; i += 3)
                {
                    int i0 = mat.indices[i + 0].id_vertex;
                    int i1 = mat.indices[i + 1].id_vertex;
                    int i2 = mat.indices[i + 2].id_vertex;

                    rigidBody2.m_listIndices.AddRange(new int[] { i0, i1, i2 });
                }
            }

            rigidBody2.Create();

            DispatcherTimer timer = new DispatcherTimer();

            timer.Tick    += Timer_Tick;;
            timer.Interval = TimeSpan.FromSeconds(0);
            timer.Start();
        }
コード例 #4
0
        //Get the coordinates of the specified jump arc where it lines up with one of the edges of a given rigidbody
        public Tuple <Tuple <Vector2D, Vector2D, Vector2D, Vector2D>, Tuple <Vector2D, Vector2D, Vector2D, Vector2D> > GetBoxCollisionPoints(RigidBody RB, Vector2D source, float accelerationTime, float totalJumpTime, Vector2D gravity)
        {
            if (float.IsNaN(accelerationTime))
            {
                return(null);
            }

            //force acceleration time to be positive (negative times are not valid)
            int sign = (int)(accelerationTime / (float)Math.Abs(accelerationTime));

            accelerationTime *= sign;


            //calculate the possible collision locations during acceleration
            Vector2D acceleration    = new Vector2D(GetHorizontalAcceleration() * sign, gravity.Y);
            Vector2D velocity        = new Vector2D(playerBody.LinearVelocity.X, jumpInitialVelocity);
            Vector2D initialPosition = new Vector2D(source);

            Tuple <Vector2D, Vector2D, Vector2D, Vector2D> resultsDuringAcc = UsefulMathsFunctions.GetArcPosAtBoxEdges(RB, initialPosition, velocity, acceleration, accelerationTime);


            //calculate the possible collision locations after acceleration
            float YatAccEnd = SuvatEquations.SfromUAT(velocity.Y, acceleration.Y, accelerationTime);
            float XatAccEnd = SuvatEquations.SfromUAT(velocity.X, acceleration.X, accelerationTime);

            initialPosition.Y += YatAccEnd;
            initialPosition.X += XatAccEnd;

            velocity.X = SuvatEquations.VfromUAT(velocity.X, acceleration.X, accelerationTime);
            velocity.Y = SuvatEquations.VfromUAT(velocity.Y, acceleration.Y, accelerationTime);

            acceleration.X = 0;

            Tuple <Vector2D, Vector2D, Vector2D, Vector2D> resultsAftergAcc = UsefulMathsFunctions.GetArcPosAtBoxEdges(RB, initialPosition, velocity, acceleration, totalJumpTime - accelerationTime);

            //return the two sets of coordinates
            return(new Tuple <Tuple <Vector2D, Vector2D, Vector2D, Vector2D>, Tuple <Vector2D, Vector2D, Vector2D, Vector2D> >(resultsDuringAcc, resultsAftergAcc));
        }
コード例 #5
0
        //Checks to see if a fall from an input coordinate TO an input coordinate would collide with a given rigidbody
        public bool FallCollidesWithRB(RigidBody RB, Vector2D source, Vector2D destination, Vector2D gravity)
        {
            //Return false if the rigid body is outside the widest possible fall range
            if (source.Y - playerRadius > RB.Shape.ComputeAABB().MAX.Y + RB.Position.Y)
            {
                return(false);
            }
            if (Math.Max(source.Y, destination.Y) + playerRadius < RB.Position.Y + RB.Shape.ComputeAABB().MIN.Y)
            {
                return(false);
            }
            if (RB.Shape.ComputeAABB().MAX.X + RB.Position.X < Math.Min(source.X, destination.X) - playerRadius)
            {
                return(false);
            }
            if (Math.Max(source.X, destination.X) + playerRadius < RB.Position.X + RB.Shape.ComputeAABB().MIN.X)
            {
                return(false);
            }


            Vector2D displacement = destination - source;

            //calculate the fall time (return no collision if the fall time was invalid)
            Tuple <float, float> timeToFall = SuvatEquations.TfromSUA(displacement.Y, 0.0f, gravity.Y);

            if (float.IsNaN(timeToFall.Item1) || timeToFall.Item1 < 0)
            {
                return(false);
            }

            //calculate the average horizontal acceleration needed to fall to the destination
            float acceleration = SuvatEquations.AfromSUT(displacement.X, 0.0f, Math.Max(timeToFall.Item1, timeToFall.Item2));

            //calculate the four points where the path defined by acceleration could potentially collide with the rigidbody
            Tuple <float, float> timeToReach;

            //obtain the X positions of the sides of the rigidbody
            float leftmostX   = (RB.Position.X + RB.Shape.ComputeAABB().MIN.X) - source.X;
            float righttmostX = (RB.Position.X + RB.Shape.ComputeAABB().MAX.X) - source.X;
            //obtain the Y positions of the top and bottom of the rigidbody
            float topY    = (RB.Position.Y + RB.Shape.ComputeAABB().MIN.Y) - source.Y;
            float bottomY = (RB.Position.Y + RB.Shape.ComputeAABB().MAX.Y) - source.Y;



            //these coords will be estimated from the above coords
            float leftmostY;
            float righttmostY;
            float topX;
            float bottomX;



            Shape temp = new Circle(playerRadius);

            //calculate the time to reach the left side of the rigidbody
            timeToReach = Physics.SuvatEquations.TfromSUA(leftmostX, 0.0f, acceleration);

            //calculate the first Y position, check it for collision, calculate the second, check for collision
            leftmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item1);
            if (!float.IsNaN(leftmostY) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(leftmostX, leftmostY) + source))
            {
                return(true);
            }
            leftmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item2);
            if (!float.IsNaN(leftmostY) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(leftmostX, leftmostY) + source))
            {
                return(true);
            }



            //calculate the time to reach the right side of the rigidbody
            timeToReach = Physics.SuvatEquations.TfromSUA(righttmostX, 0.0f, acceleration);

            //calculate the first Y position, check it for collision, calculate the second, check for collision
            righttmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item1);
            if (!float.IsNaN(righttmostY) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(righttmostX, righttmostY) + source))
            {
                return(true);
            }
            righttmostY = Physics.SuvatEquations.SfromUAT(0.0f, 98, timeToReach.Item2);
            if (!float.IsNaN(righttmostY) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(righttmostX, righttmostY) + source))
            {
                return(true);
            }



            //calculate the time to reach the top of the rigidbody
            timeToReach = Physics.SuvatEquations.TfromSUA(topY, 0.0f, 98);

            //calculate the first X position, check it for collision, calculate the second, check for collision
            topX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item1);
            if (!float.IsNaN(topX) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(topX, topY) + source))
            {
                return(true);
            }
            topX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item2);
            if (!float.IsNaN(topX) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(topX, topY) + source))
            {
                return(true);
            }



            //calculate the time to reach the bottom of the rigidbody
            timeToReach = Physics.SuvatEquations.TfromSUA(bottomY, 0.0f, 98);

            //calculate the first X position, check it for collision, calculate the second, check for collision
            bottomX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item1);
            if (!float.IsNaN(bottomX) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(bottomX, bottomY) + source))
            {
                return(true);
            }
            bottomX = Physics.SuvatEquations.SfromUAT(0.0f, acceleration, timeToReach.Item2);
            if (!float.IsNaN(bottomX) && RB.Shape.IsCollided(temp, RB.Position, new Vector2D(bottomX, bottomY) + source))
            {
                return(true);
            }


            return(false);
        }
コード例 #6
0
        //Checks to see if a jump from source to destination would collid with the provided rigidbody
        public bool JumpCollidesWithRB(RigidBody RB, Vector2D source, Vector2D destination, Vector2D gravity)
        {
            //Get the max Y displacement
            float maxYRange = SuvatEquations.SFromUVA(jumpInitialVelocity, 0.0f, gravity.Y);

            //Return false if the rigid body is outside the widest possible jump range
            if (maxYRange + source.Y - playerRadius > RB.Shape.ComputeAABB().MAX.Y + RB.Position.Y)
            {
                return(false);
            }
            if (Math.Max(source.Y, destination.Y) + playerRadius < RB.Position.Y + RB.Shape.ComputeAABB().MIN.Y)
            {
                return(false);
            }
            if (RB.Shape.ComputeAABB().MAX.X + RB.Position.X < Math.Min(source.X, destination.X) - playerRadius)
            {
                return(false);
            }
            if (Math.Max(source.X, destination.X) + playerRadius < RB.Position.X + RB.Shape.ComputeAABB().MIN.X)
            {
                return(false);
            }


            Vector2D displacement = destination - source;

            //calculate the jump's acceleration duration, and total duration
            float accelerationTime = GetJumpFromSourceToDest(source, destination, gravity);
            float totalJumpTime    = GetTotalJumpDuration(source, destination, gravity);

            //if the jump is not valid, return that it does not collide with the rigidbody
            if (float.IsNaN(totalJumpTime) || totalJumpTime < 0)
            {
                return(false);
            }


            //calculate the 8 points that could potentially intersect with the box (1 before and 1 after the jump's apex)
            Tuple <Tuple <Vector2D, Vector2D, Vector2D, Vector2D>, Tuple <Vector2D, Vector2D, Vector2D, Vector2D> > boxCollisionPoints = GetBoxCollisionPoints(RB, source, accelerationTime, totalJumpTime, gravity);

            if (boxCollisionPoints == null)
            {
                return(true);
            }

            //check to see if the player would collide with the rigidbody at any of the calculated positions
            Shape temp = new Circle(playerRadius);

            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item1.Item1))
            {
                return(true);
            }
            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item1.Item2))
            {
                return(true);
            }
            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item1.Item3))
            {
                return(true);
            }
            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item1.Item4))
            {
                return(true);
            }

            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item2.Item1))
            {
                return(true);
            }
            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item2.Item2))
            {
                return(true);
            }
            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item2.Item3))
            {
                return(true);
            }
            if (RB.Shape.IsCollided(temp, RB.Position, boxCollisionPoints.Item2.Item4))
            {
                return(true);
            }


            return(false);
        }