Пример #1
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        void Update()
        {
            // UPDATE the physics!
            for (int i = 0; i < 3; i++)
            {
                mWorld.update(1 / 120f);
            }

            // cursor movement.
            cursorPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            // if the user presses the A button, create a new body at the cursor position.
            if (Input.GetKeyDown(KeyCode.A))
            {
                GameObject s = new GameObject();
                JelloPhysics.ClosedShape shape = new JelloPhysics.ClosedShape();

                shape.begin();
                shape.addVertex(new Vector2(-1.0f, 0f));
                shape.addVertex(new Vector2(0f, 1.0f));
                shape.addVertex(new Vector2(1.0f, 0f));
                shape.addVertex(new Vector2(0f, -1.0f));
                shape.finish();

                DraggableSpringBody body = new DraggableSpringBody();
                body.Setup(mWorld, shape, 1f, 150, 5, 300, 15, new Vector2(cursorPos.x, cursorPos.y), ((float)UnityEngine.Random.Range(0, 360)), Vector2.one);

                body.addInternalSpring(0, 2, 400f, 12f);
                body.addInternalSpring(1, 3, 400f, 12f);
            }

            if (Input.GetKeyDown(KeyCode.B))
            {
                GameObject s = new GameObject();
                JelloPhysics.ClosedShape shape = new JelloPhysics.ClosedShape();

                shape.begin();
                for (int i = 0; i < 360; i += 20)
                {
                    shape.addVertex(new Vector2((float)Mathf.Cos(((float)-i) * Mathf.Deg2Rad), (float)Mathf.Sin(((float)-i) * Mathf.Deg2Rad)));
                }
                shape.finish();

                DraggablePressureBody pb = new DraggablePressureBody();
                pb.Setup(mWorld, shape, 1.0f, 40.0f, 10.0f, 1.0f, 300.0f, 20.0f, cursorPos, 0, Vector2.one);
                pb.addTriangle(0, 10, 9);
                pb.addTriangle(0, 9, 1);
                pb.addTriangle(1, 9, 8);
                pb.addTriangle(1, 8, 2);
                pb.addTriangle(2, 8, 7);
                pb.addTriangle(2, 7, 3);
                pb.addTriangle(3, 7, 6);
                pb.addTriangle(3, 6, 4);
                pb.addTriangle(4, 6, 5);
                pb.addTriangle(17, 10, 0);
                pb.addTriangle(17, 11, 10);
                pb.addTriangle(16, 11, 17);
                pb.addTriangle(16, 12, 11);
                pb.addTriangle(15, 12, 16);
                pb.addTriangle(15, 13, 12);
                pb.addTriangle(14, 12, 15);
                pb.addTriangle(14, 13, 12);
                pb.finalizeTriangles(Color.white);

                pb.addInternalSpring(0, 2, 400f, 12f);
                pb.addInternalSpring(1, 3, 400f, 12f);
            }

            // dragging!
            if (Input.GetMouseButton(0))
            {
                if (dragBody != null)
                {
                    PointMass pm = dragBody.getPointMass(dragPoint);
                    if (dragBody.GetType().Name == "DraggableSpringBody")
                    {
                        ((DraggableSpringBody)dragBody).setDragForce(JelloPhysics.VectorTools.calculateSpringForce(pm.Position, pm.Velocity, cursorPos, Vector2.zero, 0.0f, 100.0f, 10.0f), dragPoint);
                    }
                    else if (dragBody.GetType().Name == "DraggablePressureBody")
                    {
                        ((DraggablePressureBody)dragBody).setDragForce(JelloPhysics.VectorTools.calculateSpringForce(pm.Position, pm.Velocity, cursorPos, Vector2.zero, 0.0f, 100.0f, 10.0f), dragPoint);
                    }
                }
            }
            else
            {
                dragBody  = null;
                dragPoint = -1;
            }

            if (Input.GetMouseButtonDown(0))
            {
                if (dragBody == null)
                {
                    int body;
                    mWorld.getClosestPointMass(cursorPos, out body, out dragPoint);
                    dragBody = mWorld.getBody(body);
                }
            }
        }
Пример #2
0
        private void _handleCollisions()
        {
            // handle all collisions!
            for (int i = 0; i < mCollisionList.Count; i++)
            {
                BodyCollisionInfo info = mCollisionList[i];

                PointMass A  = info.bodyA.getPointMass(info.bodyApm);
                PointMass B1 = info.bodyB.getPointMass(info.bodyBpmA);
                PointMass B2 = info.bodyB.getPointMass(info.bodyBpmB);

                // velocity changes as a result of collision.
                Vector2 bVel = new Vector2();
                bVel.x = (B1.Velocity.x + B2.Velocity.x) * 0.5f;
                bVel.y = (B1.Velocity.y + B2.Velocity.y) * 0.5f;

                Vector2 relVel = new Vector2();
                relVel.x = A.Velocity.x - bVel.x;
                relVel.y = A.Velocity.y - bVel.y;

                float relDot;
//                Vector2.Dot(ref relVel, ref info.normal, out relDot);
                relDot = Vector2.Dot(relVel, info.normal);

                // collision filter!
                if (!mMaterialPairs[info.bodyA.Material, info.bodyB.Material].CollisionFilter(info.bodyA, info.bodyApm, info.bodyB, info.bodyBpmA, info.bodyBpmB, info.hitPt, relDot))
                {
                    continue;
                }

                if (info.penetration > mPenetrationThreshold)
                {
                    //Console.WriteLine("penetration above Penetration Threshold!!  penetration={0}  threshold={1} difference={2}",
                    //    info.penetration, mPenetrationThreshold, info.penetration-mPenetrationThreshold);

                    mPenetrationCount++;
                    continue;
                }

                float b1inf = 1.0f - info.edgeD;
                float b2inf = info.edgeD;

                float b2MassSum = ((float.IsPositiveInfinity(B1.Mass)) || (float.IsPositiveInfinity(B2.Mass))) ? float.PositiveInfinity : (B1.Mass + B2.Mass);

                float massSum = A.Mass + b2MassSum;

                float Amove;
                float Bmove;
                if (float.IsPositiveInfinity(A.Mass))
                {
                    Amove = 0f;
                    Bmove = (info.penetration) + 0.001f;
                }
                else if (float.IsPositiveInfinity(b2MassSum))
                {
                    Amove = (info.penetration) + 0.001f;
                    Bmove = 0f;
                }
                else
                {
                    Amove = (info.penetration * (b2MassSum / massSum));
                    Bmove = (info.penetration * (A.Mass / massSum));
                }

                float B1move = Bmove * b1inf;
                float B2move = Bmove * b2inf;

                float AinvMass = (float.IsPositiveInfinity(A.Mass)) ? 0f : 1f / A.Mass;
                float BinvMass = (float.IsPositiveInfinity(b2MassSum)) ? 0f : 1f / b2MassSum;

                float   jDenom = AinvMass + BinvMass;
                Vector2 numV   = new Vector2();
                float   elas   = 1f + mMaterialPairs[info.bodyA.Material, info.bodyB.Material].Elasticity;
                numV.x = relVel.x * elas;
                numV.y = relVel.y * elas;

                float jNumerator;
//                Vector2.Dot(ref numV, ref info.normal, out jNumerator);
                jNumerator = Vector2.Dot(numV, info.normal);
                jNumerator = -jNumerator;

                float j = jNumerator / jDenom;

                if (!float.IsPositiveInfinity(A.Mass))
                {
                    A.Position.x += info.normal.x * Amove;
                    A.Position.y += info.normal.y * Amove;
                }

                if (!float.IsPositiveInfinity(B1.Mass))
                {
                    B1.Position.x -= info.normal.x * B1move;
                    B1.Position.y -= info.normal.y * B1move;
                }

                if (!float.IsPositiveInfinity(B2.Mass))
                {
                    B2.Position.x -= info.normal.x * B2move;
                    B2.Position.y -= info.normal.y * B2move;
                }

                Vector2 tangent = new Vector2();
                VectorTools.getPerpendicular(ref info.normal, ref tangent);
                float friction = mMaterialPairs[info.bodyA.Material, info.bodyB.Material].Friction;
                float fNumerator;
//                Vector2.Dot(ref relVel, ref tangent, out fNumerator);
                fNumerator  = Vector2.Dot(relVel, tangent);
                fNumerator *= friction;
                float f = fNumerator / jDenom;

                // adjust velocity if relative velocity is moving toward each other.
                if (relDot <= 0.0001f)
                {
                    if (!float.IsPositiveInfinity(A.Mass))
                    {
                        A.Velocity.x += (info.normal.x * (j / A.Mass)) - (tangent.x * (f / A.Mass));
                        A.Velocity.y += (info.normal.y * (j / A.Mass)) - (tangent.y * (f / A.Mass));
                    }

                    if (!float.IsPositiveInfinity(b2MassSum))
                    {
                        B1.Velocity.x -= (info.normal.x * (j / b2MassSum) * b1inf) - (tangent.x * (f / b2MassSum) * b1inf);
                        B1.Velocity.y -= (info.normal.y * (j / b2MassSum) * b1inf) - (tangent.y * (f / b2MassSum) * b1inf);
                    }

                    if (!float.IsPositiveInfinity(b2MassSum))
                    {
                        B2.Velocity.x -= (info.normal.x * (j / b2MassSum) * b2inf) - (tangent.x * (f / b2MassSum) * b2inf);
                        B2.Velocity.y -= (info.normal.y * (j / b2MassSum) * b2inf) - (tangent.y * (f / b2MassSum) * b2inf);
                    }
                }
            }
            mCollisionList.Clear();
        }