/// <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); } } }
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(); }