C++ Jittery游戏循环 - 如何让它尽可能顺畅?

Acc*_*tor 0 c++ math timing game-loop jitter

这是我的游戏循环代码:

        while (shouldUpdate)
        {
            timeSinceLastUpdate = 0;
            startTime = clock();

                while (timeAccumulator >= timeDelta)
                {
                    listener.handle();
                    em.update();
                    timeAccumulator -= timeDelta;
                    timeSinceLastUpdate += timeDelta;
                }

            rm.beginRender();
                _x->draw();
            rm.endRender();

            timeAccumulator += clock() - startTime;
        }
Run Code Online (Sandbox Code Playgroud)

它几乎完美地运行,但它有一些抖动,每秒几次而不是_x(一个测试实体,它在更新中所做的全部是x ++)向右移动1个像素,它实际上向右移动2个像素这是一个明显的滞后/抖动效应.我猜时钟()不够准确.那么我该怎么做才能改善这个游戏循环呢?

如果重要,我使用SDL和SDL_image.

编辑:做一些比时钟更精确的事情没有任何改变.但是,我已经想到的是,这一切都归功于timeDelta.这就是我发这篇文章时timeDelta的定义方式:

double timeDelta = 1000/60;
Run Code Online (Sandbox Code Playgroud)

但当我把它定义为别的东西时,却一直在搞乱......

double timeDelta = 16.666666;
Run Code Online (Sandbox Code Playgroud)

我注意到比赛开始的前几秒,它像黄油一样光滑.但就在几秒钟之后,游戏结结巴巴,然后又恢复了平稳,并重复了这样.我添加了更多的6(或真正的)之后的任何东西,游戏最初平滑的时间越长,并且它的延迟越大.似乎浮动错误正在攻击.那我该怎么办呢?

编辑2:我已经尝试了很多东西,现在它甚至都不好笑......有人可以帮助我完成循环的数学部分吗?既然这就是造成这种情况的原因......

EDIT3:我给一些人发了一个测试程序,有人说它非常顺利,有些人说它像我描述的那样紧张.对于愿意在这里测试它的人来说,它是(src):https://www.mediafire.com/?vfpy4phkdj97q9j

EDIT4:我改变了源代码的链接.

Cof*_*ode 7

几乎可以肯定是因为它的准确性 clock()

二者必选其一std::chronoSDL_GetTicks()测量自纪元时间.

我建议使用std::chrono只是因为我更喜欢C++ api,这是一个例子:

int main(){
    using clock = std::chrono::high_resolution_clock;
    using milliseconds = std::chrono::milliseconds;
    using std::chrono::duration_cast;

    auto start = clock::now(), end = clock::now();
    uint64_t diff;


    while(running){
        diff = duration_cast<milliseconds>(end - start).count();
        start = clock::now();     

        // do time difference related things

        end = clock::now();
    }
}
Run Code Online (Sandbox Code Playgroud)

要仅在指定的增量后更新,您可以像这样执行循环:

int main(){
    auto start = clock::now(), end = clock::now();
    uint64_t diff = duration_cast<milliseconds>(end - start).count();

    auto accum_start = clock::now();
    while(running){
        start = clock::now();
        diff = duration_cast<milliseconds>(end - start).count();

        if(duration_cast<nanoseconds>(clock::now() - accum_start).count() >= 16666666){
            // do render updates every 60th of a second
            accum_start = clock::now();
        }

        end = clock::now();
    }
}
Run Code Online (Sandbox Code Playgroud)

start并且end都将是类型的std::chrono::time_point<clock>地方clock是我们以前所定义std::chrono::high_resolution_clock.

2之差time_point的将是一个std::chrono::duration其可以是纳秒,毫秒或任何你喜欢的其它单元.我们将其转换为毫秒,然后将count()其分配给我们uint64_t.如果你喜欢,可以使用其他整数类型.

diff是你应该如何计算你的timeDelta.您不应其设置为常量.即使你确定它是正确的,你也错了.每帧都有不同的delta,即使它是一秒的最小分数.

如果要设置恒定的帧差异,请使用SDL_GL_SetSwapInterval设置垂直同步.

编辑

只为你,我创建了这个例子git repo.请注意main.cpp我乘以diff得到每帧的调整差异.这种调整(或缺乏)是您获得抖动的地方.