如何在box2d中修复时间步,以便精灵顺利移动?

时间:2015-08-12 10:46:35

标签: c++ box2d

以下是我的时间步骤:

void step(float dt){
    static double UPDATE_INTERVAL = 1.0f/60.0f;
    static double MAX_CYCLES_PER_FRAME = 5;
    static double timeAccumulator = 0;

    timeAccumulator += dt;
    if (timeAccumulator > (MAX_CYCLES_PER_FRAME * UPDATE_INTERVAL))
    {
        timeAccumulator = UPDATE_INTERVAL;
    }

    int32 velocityIterations = 3;
    int32 positionIterations = 2;
    while (timeAccumulator >= UPDATE_INTERVAL)
    {
        timeAccumulator -= UPDATE_INTERVAL;
        this->world->Step(UPDATE_INTERVAL,
                          velocityIterations, positionIterations);
        this->world->ClearForces();
    }
}

虽然这样的游戏无论帧速率如何都能很好地工作,但即使帧速率为60fps,也会导致精灵“颤抖”或“断断续续”!

我认为这是因为每个帧的精灵移动的量不同,因为每个帧的while循环执行的次数是不同的。

修复时间步的更好方法是什么?我已经阅读了很多关于修复时间步骤的文章,我感到非常困惑。除了口吃之外,上述“有效”。

编辑:只是为了澄清,颤抖很小!视力不好的人不会注意到它,但如果仔细观察,它会让游戏看起来预算很低。它使游戏看起来不顺畅。

1 个答案:

答案 0 :(得分:0)

你没有正确地控制你的时间累积器:

timeAccumulator += dt;
if (timeAccumulator > (MAX_CYCLES_PER_FRAME * UPDATE_INTERVAL))
{
    timeAccumulator = UPDATE_INTERVAL;
}

应该是

timeAccumulator = std::min(dt + timeAccumulator, MAX_CYCLES_PER_FRAME * UPDATE_INTERVAL;

关于步进:您需要根据timeAccumulator中的遗留内容,在下一个完整步骤中插入最后一个完整步骤。那是tutorial on this by Allan Bishop。这是他的平滑步骤(只有最后一步与分数步骤)的结果:

// for the remaining timeAccumulator < UPDATE_INTERVAL
fixedTimestepAccumulatorRatio = timeAccumulator / UPDATE_INTERVAL;

private function smoothStates():void
{
    const oneMinusRatio:Number = 1.0 - fixedTimestepAccumulatorRatio;
    //Makes it easier to wrap up the Box2D body in another object so we can track other variables.
    for each (var body:Body in bodies)
    {
        var box2Dbody = body.box2DBody;
        texture.position.x = fixedTimestepAccumulatorRatio * box2Dbody.GetPosition().x + oneMinusRatio * body.previousPosition.x;
        texture.position.y = fixedTimestepAccumulatorRatio * box2Dbody.GetPosition().y + oneMinusRatio * body.previousPosition.y;
        texture.rotation = box2Dbody.GetAngle() * fixedTimestepAccumulatorRatio + oneMinusRatio * body.previousAngle;
    }
}