在Box2D中制作一个漩涡

时间:2011-12-19 18:22:22

标签: c++ objective-c box2d physics quartz-graphics

我试图通过施加力在C ++ / Objective C上的Box2D中制作螺旋涡旋。 我想要意识到的是一个漩涡,它将身体从一个点推出,或吸引它们。 我想我将不得不申请多个部队。

我在这个问题上的切入点是:

我想我必须施加3种力量: - 从中​​心吸引或排斥身体的冲动。 - 让它在螺旋上横向移动的冲动,但......怎么样? - 如果冲动对我不起作用,则转动身体本身的扭矩。

2 个答案:

答案 0 :(得分:3)

我曾经做过一个旋转平台,制作了一个圆形传感器,它通过圆形矢量场给人体施加切向速度变化。我使用的圆形矢量场是这样的:

V = (y, -x)

此向量字段的直观表示可在此处找到: http://kasadkad.files.wordpress.com/2009/09/derham1.png?w=450&h=427

y和x是身体与传感器中心的相对位置,因此您可以这样做:

Vector getTangentVector(Vector relativePosition, bool invert)
{
    Vector vec;
    if(invert) //if it's cw or ccw
    {
        vec.setY(relativePosition.x());
        vec.setX(-relativePosition.y());
    }
    else
    {
        vec.setY(-relativePosition.x());
        vec.setX(relativePosition.y());
    }
    return vec;
}

然后在我的程序的更新方法上,我做了类似的事情:

for (b2ContactEdge* ce = platformBody->GetContactList(); ce; ce = ce->next)
{

    b2Contact* c = ce->contact;

    if(c->IsTouching())
    {
        const b2Body* bodyA = c->GetFixtureA()->GetBody();
        const b2Body* bodyB = c->GetFixtureB()->GetBody();

        const b2Body* targetBody = (bodyA == platformBody)?bodyB:bodyA;

        Vector speed = getTangentImpulse(
                          getRelativePosition(platformBody, targetBody),
                          true);


        speed *= CONSTANT; // CONSTANT = 1.8, 
                           // this is to account for the targetBody attrition, 
                           // so it doesn't slip on the platform

        Vector currentSpeed;
        currentSpeed.setX(targetBody->GetLinearVelocity().x);
        currentSpeed.setY(targetBody->GetLinearVelocity().y);



        Vector diff = speed - currentSpeed;
        diff *= 0.01; //should depend on time, but this worked nicely. It makes the
                      //body change its linear velocity to be the same as "speed" at a 
                      //0.01 change rate.

        currentSpeed += diff;
        targetBody->SetLinearVelocity(
                               b2Vec2(currentSpeed.x(), 
                               currentSpeed.y()));

    }

}

此解决方案中有很多变通方法,例如,我不使用冲动并手动更改速度,它对我来说效果更好。另外,我使用常数来计算损耗。

它仍然产生了我需要的效果,所以我希望它适合你。对于漩涡,我猜你只需要连接一个关节,如鼠标关节,连接到中心并抓住身体。如果仅使用关节,则很难使其足够强壮以抓住身体,但足够弱以使其围绕中心旋转。与我的代码一起,通过使用常量来实现这一点可能更容易。

我希望这会有所帮助。

编辑:我只记得,通过平台代码,您还可以确保旋转的方向,这对于关节来说是不可能的。

答案 1 :(得分:0)

我通过对每个小行星使用距离关节,然后施加切向力使它们围绕中心“旋转”,围绕中心点创建了一系列旋转小行星。

您可以用指向涡旋中心的实际力替换距离关节。您还可以慢慢减小距离关节中的距离以使项目“螺旋”进入。我将继续使用它,因为它可以让您更好地控制物品进入涡流的速度。

我将“myBodyA”称为旋涡中心的身体。

来自Box2d手册:

b2DistanceJointDef jointDef;
jointDef.Initialize(myBodyA, myBodyB, worldAnchorOnBodyA, worldAnchorOnBodyB); jointDef.collideConnected = true;
world->CreateJoint(&jointDef);

你必须向你的身体施加一些力(让我们说它是myBodyB)才能让它向正确的方向移动,以便它围绕myBodyA旋转。这需要一些数学。

你想要做的是计算垂直于从myBodyB指向myBodyA的向量的向量。您可以通过找到myBodyB到myBodyA的向量,对其进行标准化,对其进行偏斜(按PI / 2旋转),然后将其用作力方向来完成此操作。类似的东西:

// Calculate Tangent Vector
b2Vec2 radius = myBodyB.GetPosition()-myBodyA.GetPosition();
b2Vec2 tangent = radius.Skew();
tangent.Normalize();

// Apply some force along tangent
myBodyB.ApplyForceToCenter(body->GetMass()*acceleration*vTangent);

如果你读得正确,可以看到F = m * a * tangentVector;也就是说,你在切线的方向施加力。我相信它会顺时针旋转它(如果我做了正确的数学运算)。无论如何,对力的负面影响会将其向相反方向移动。

要停止身体旋转,可以在其上使用SetLinearDamping(dampingValue)。所以只要你施加力,它就会继续旋转。如果你停止施力,它应该轻轻停止。您可以通过加速度值和dampingValue参数控制加速/减速。

如果你真的想要很好地控制速度,我相信你可以这样做来控制速度:

b2Vec2 linVel = myBodyB.GetLinearVelocity();
linVel.Normalize();
linVel *= maxSpeed;
myBodyB.SetLinearVelocity(linVel);

这有用吗?