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 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.
更多精彩
赞助商链接