我希望使用Box2D模拟牛顿万有引力定律,属于编程相关内容。我已经查阅了手册,但没有找到具体方法。我的目标是在空间中(零重力)放置多个物体并模拟运动。请问是否有什么建议?
实现起来相当简单:
for ( int i = 0; i < numBodies; i++ ) {
b2Body* bi = bodies[i];
b2Vec2 pi = bi->GetWorldCenter();
float mi = bi->GetMass();
for ( int k = i; k < numBodies; k++ ) {
b2Body* bk = bodies[k];
b2Vec2 pk = bk->GetWorldCenter();
float mk = bk->GetMass();
b2Vec2 delta = pk - pi;
float r = delta.Length();
float force = G * mi * mk / (r*r);
delta.Normalize();
bi->ApplyForce( force * delta, pi );
bk->ApplyForce( -force * delta, pk );
}
}
v += h * b->m_invMass * (b->m_gravityScale * b->m_mass * gravity + b->m_force);
使用
int planet_x = 0;
int planet_y = 0;
b2Vec2 gravityVector = (b2Vec2(planet_x, planet_y) - b->GetPosition());
gravityVector.Normalize();
gravityVector.x = gravityVector.x * 10.0f;
gravityVector.y = gravityVector.y * 10.0f;
v += h * b->m_invMass * (b->m_gravityScale * b->m_mass * gravityVector + b->m_force);
如果你只有一个星球,那么这是一个简单的解决方案。 如果你希望距离越远受到的力越小,可以使用1/gravityVector代替归一化。这样也可以将两个星球的引力相加。然后你还可以遍历星球列表并将引力向量相加。
此外,实现像b2World::CreatePlanet这样的函数可能会很有用。
10.0f只是对地球上的9.81f的近似值,你可能需要进行调整。如果行星的质量很重要,你可能需要乘以一个常数来使其更加逼真,或者只需增加物体的密度以使其与行星的实际重量相匹配。
当然,你也可以将重力设置为0,0,然后在每个对象的每个步骤之前计算它,但这可能会影响性能。