WEB开发网
开发学院图形图像Flash Managing multiple gravities with Box2D 阅读

Managing multiple gravities with Box2D

 2009-10-20 00:00:00 来源:WEB开发网   
核心提示: And this is the result:The result is what we want, anyway now you may say to create objects that aren’t affected by gravity you just have to c

And this is the result:

The result is what we want, anyway now you may say to create objects that aren’t affected by gravity you just have to change line 88 with

ant_gravity = new b2Vec2(0.0,-10.0*bb.GetMass());

but look at the result…

circles are slowly falling down. This happens because when you call Step functions, bodies have an acceleration due to gravity, and the opposite force isn’t enough to nullify it.

Let’s see the second method, called

The island method

This method is named after the filename of the library you have to edit… it’s b2Island.as inside Dynamics folder.

First, the only line inside Update function must be once again

m_world.Step(m_timeStep, m_iterations);

as in the first example.

Then, this is the modified version of Solve function inside b2Island.as file:

public function Solve(step:b2TimeStep, gravity:b2Vec2, correctPositions:Boolean, allowSleep:Boolean) : void
{
 var i:int;
 var b:b2Body;
 var joint:b2Joint;
 var applied_gravity:b2Vec2
 
 // Integrate velocities and apply damping.
 for (i = 0; i < m_bodyCount; ++i)
 {
  b = m_bodies[i];
 
  if (b.IsStatic())
   continue;
 
  // Integrate velocities.
  //b.m_linearVelocity += step.dt * (gravity + b.m_invMass * b.m_force);
  if(b.m_userData.name=="circle"){
   applied_gravity = new b2Vec2(-gravity.x,-gravity.y)
  }
  else{
   applied_gravity = gravity;
  }
  b.m_linearVelocity.x += step.dt * (applied_gravity.x + b.m_invMass * b.m_force.x);
  b.m_linearVelocity.y += step.dt * (applied_gravity.y + b.m_invMass * b.m_force.y);
  b.m_angularVelocity += step.dt * b.m_invI * b.m_torque;
 
  // Reset forces.
  b.m_force.SetZero();
  b.m_torque = 0.0;
 
  // Apply damping.
  // ODE: dv/dt + c * v = 0
  // Solution: v(t) = v0 * exp(-c * t)
  // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt)
  // v2 = exp(-c * dt) * v1
  // Taylor expansion:
  // v2 = (1.0f - c * dt) * v1
  b.m_linearVelocity.Multiply( b2Math.b2Clamp(1.0 - step.dt * b.m_linearDamping, 0.0, 1.0) );
  b.m_angularVelocity *= b2Math.b2Clamp(1.0 - step.dt * b.m_angularDamping, 0.0, 1.0);
 
  // Check for large velocities.
  //if (b2Dot(b->m_linearVelocity, b->m_linearVelocity) > b2_maxLinearVelocitySquared)
  if ((b.m_linearVelocity.LengthSquared()) > b2Settings.b2_maxLinearVelocitySquared)
  {
   b.m_linearVelocity.Normalize();
   b.m_linearVelocity.x *= b2Settings.b2_maxLinearVelocity;
   b.m_linearVelocity.y *= b2Settings.b2_maxLinearVelocity;
  }
 
  if (b.m_angularVelocity * b.m_angularVelocity > b2Settings.b2_maxAngularVelocitySquared)
  {
   if (b.m_angularVelocity < 0.0)
   {
    b.m_angularVelocity = -b2Settings.b2_maxAngularVelocity;
   }
   else
   {
    b.m_angularVelocity = b2Settings.b2_maxAngularVelocity;
   }
  }
 }
 
 var contactSolver:b2ContactSolver = new b2ContactSolver(step, m_contacts, m_contactCount, m_allocator);
 
 // Initialize velocity constraints.
 contactSolver.InitVelocityConstraints(step);
 
 for (i = 0; i < m_jointCount; ++i)
 {
  joint = m_joints[i];
  joint.InitVelocityConstraints(step);
 }
 
 // Solve velocity constraints.
 for (i = 0; i < step.maxIterations; ++i)
 {
  contactSolver.SolveVelocityConstraints();
 
  for (var j:int = 0; j < m_jointCount; ++j)
  {
   joint = m_joints[j];
   joint.SolveVelocityConstraints(step);
  }
 }
 
 // Post-solve (store impulses for warm starting).
 contactSolver.FinalizeVelocityConstraints();
 
 // Integrate positions.
 for (i = 0; i < m_bodyCount; ++i)
 {
  b = m_bodies[i];
 
  if (b.IsStatic())
   continue;
 
  // Store positions for continuous collision.
  b.m_sweep.c0.SetV(b.m_sweep.c);
  b.m_sweep.a0 = b.m_sweep.a;
 
  // Integrate
  //b.m_sweep.c += step.dt * b.m_linearVelocity;
  b.m_sweep.c.x += step.dt * b.m_linearVelocity.x;
  b.m_sweep.c.y += step.dt * b.m_linearVelocity.y;
  b.m_sweep.a += step.dt * b.m_angularVelocity;
 
  // Compute new transform
  b.SynchronizeTransform();
 
  // Note: shapes are synchronized later.
 }
 
 if (correctPositions)
 {
  // Initialize position constraints.
  // Contacts don't need initialization.
  for (i = 0; i < m_jointCount; ++i)
  {
   joint = m_joints[i];
   joint.InitPositionConstraints();
  }
 
  // Iterate over constraints.
  for (m_positionIterationCount = 0; m_positionIterationCount < step.maxIterations; ++m_positionIterationCount)
  {
   var contactsOkay:Boolean = contactSolver.SolvePositionConstraints(b2Settings.b2_contactBaumgarte);
 
   var jointsOkay:Boolean = true;
   for (i = 0; i < m_jointCount; ++i)
   {
    joint = m_joints[i];
    var jointOkay:Boolean = joint.SolvePositionConstraints();
    jointsOkay = jointsOkay && jointOkay;
   }
 
   if (contactsOkay && jointsOkay)
   {
    break;
   }
  }
 }
 
 Report(contactSolver.m_constraints);
 
 if (allowSleep){
 
  var minSleepTime:Number = Number.MAX_VALUE;
 
  var linTolSqr:Number = b2Settings.b2_linearSleepTolerance * b2Settings.b2_linearSleepTolerance;
  var angTolSqr:Number = b2Settings.b2_angularSleepTolerance * b2Settings.b2_angularSleepTolerance;
 
  for (i = 0; i < m_bodyCount; ++i)
  {
   b = m_bodies[i];
   if (b.m_invMass == 0.0)
   {
    continue;
   }
 
   if ((b.m_flags & b2Body.e_allowSleepFlag) == 0)
   {
    b.m_sleepTime = 0.0;
    minSleepTime = 0.0;
   }
 
   if ((b.m_flags & b2Body.e_allowSleepFlag) == 0 ||
    b.m_angularVelocity * b.m_angularVelocity > angTolSqr ||
    b2Math.b2Dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr)
   {
    b.m_sleepTime = 0.0;
    minSleepTime = 0.0;
   }
   else
   {
    b.m_sleepTime += step.dt;
    minSleepTime = b2Math.b2Min(minSleepTime, b.m_sleepTime);
   }
  }
 
  if (minSleepTime >= b2Settings.b2_timeToSleep)
  {
   for (i = 0; i < m_bodyCount; ++i)
   {
    b = m_bodies[i];
    b.m_flags |= b2Body.e_sleepFlag;
    b.m_linearVelocity.SetZero();
    b.m_angularVelocity = 0.0;
   }
  }
 }
}

Let’s see the lines I added/changed:

Line 162: declaring a new vector that will handle the applied gravity

Line 174: if the body we are solving is called “circle”…

Line 175: set applied_gravity vector as the opposite of the default gravity one

Lines 177-179: If not, set applied_gravity vector to default gravity one

Lines 180-181: Use applied_gravity vector instead of gravity vector to determine body’s linear velocity

And this is the result:

That is working perfectly even if you change line 175 this way:

applied_gravity = new b2Vec2(0,0)

To have no gravity circles, so this last method is preferred.

Let me think what do you think about it.

上一页  1 2 3 

Tags:Managing multiple gravities

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接