首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在box2d中固定时间步长,以使精灵平滑移动?

如何在box2d中固定时间步长,以使精灵平滑移动?
EN

Stack Overflow用户
提问于 2015-08-12 18:46:35
回答 1查看 604关注 0票数 0

下面是我的时间步长:

代码语言:javascript
复制
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循环的次数是不同的。

固定时间步长的更好方法是什么?我读了很多关于固定时间步长的文章,感到非常困惑。上面的“工作”除了卡顿。

编辑:只是为了澄清,颤动非常小!视力不佳的人不会注意到这一点,但如果你仔细观察,它会使游戏看起来非常低的预算。这让游戏看起来并不流畅。

EN

回答 1

Stack Overflow用户

发布于 2015-08-12 18:56:00

你没有正确夹住你的timeAccumulator:

代码语言:javascript
复制
timeAccumulator += dt;
if (timeAccumulator > (MAX_CYCLES_PER_FRAME * UPDATE_INTERVAL))
{
    timeAccumulator = UPDATE_INTERVAL;
}

应该是

代码语言:javascript
复制
timeAccumulator = std::min(dt + timeAccumulator, MAX_CYCLES_PER_FRAME * UPDATE_INTERVAL);

关于单步执行:您需要根据timeAccumulator中的剩余部分,用下一个完整的步骤插入上一个完整的步骤。Allan Bishop有一个关于这方面的教程,尽管原始站点不再可访问(blog.allanbishop.com)。下面是他平滑步骤(只有最后一个具有小数步骤)的样子:

代码语言:javascript
复制
// 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;
    }
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31962978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档