这是我的游戏循环代码:
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;
}
它几乎完美地运行,但它有一些抖动,每秒几次而不是_x(一个测试实体,它在更新中所做的全部是x ++)向右移动1个像素,它实际上移动2个像素到正确的,这是一个明显的滞后/抖动效应。我猜时钟()不够准确。那么我该怎么做才能改善这个游戏循环呢?
如果重要,我使用SDL和SDL_image。
编辑:做一些比时钟更精确的事情后没有任何改变。但是,我已经想到的是,这一切都归功于timeDelta。这就是我发这篇文章时定义timeDelta的方式:
double timeDelta = 1000/60;
但是当我把它定义为其他东西时,却在乱搞......
double timeDelta = 16.666666;
我注意到比赛开始的前几秒,它像黄油一样光滑。但就在几秒钟之后,游戏结结巴巴,然后又恢复了平稳,并重复了这样。我添加了更多的6(或真正的)之后的任何东西,游戏最初平滑的时间越长,并且它的延迟越大。似乎浮动错误正在攻击。那我该怎么办呢?
EDIT2:我已经尝试了很多东西,现在它甚至都不好笑......有人可以帮助我完成循环的数学部分吗?因为这是造成这种情况的原因......
编辑3:我向一些人发送了一个测试程序,有些人说它非常顺利,其他人说它像我描述的那样紧张。对于愿意在这里测试它的人来说,它是(src):hereEDIT4: 我将链接更改为源代码 。
答案 0 :(得分:7)
几乎可以肯定是因为clock()
使用std::chrono
或SDL_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();
}
}
要仅在指定的增量后更新,您可以像这样执行循环:
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();
}
}
start
和end
都属于std::chrono::time_point<clock>
类型,其中clock
之前已被我们定义为std::chrono::high_resolution_clock
。
2 time_point
&#39}之间的差异将是std::chrono::duration
,可以是纳秒,毫秒或您喜欢的任何其他单位。我们将其转换为毫秒,然后将count()
分配给我们的uint64_t
。如果你愿意,可以使用其他整数类型。
我的diff
是您应该如何计算timeDelta
。您应该不将其设置为常量。即使你确定它是正确的,你也错了。每个帧都有不同的增量,即使它是一秒的最小分数。
如果要设置恒定的帧差异,请使用SDL_GL_SetSwapInterval设置垂直同步。
仅为您,我在main.cpp
中创建了this example git repo.通知,其中我乘以diff
以获得每帧的调整差异。这种调整(或缺乏)是你获得抖动的地方。