我的固定时间步长与增量时间和插值的解决方案是错误的吗?
Is my solution to fixed timestep with delta time and interpolation wrong?
我正在尝试编写具有固定增量时间的简单循环,用于物理和插值,然后再渲染状态。我正在固定时间步长的游戏教程中使用 Gaffer,我试图理解它并使其工作。
float timeStep = 0.01;
float alpha = 1.0;
while (isOpen()) {
processInput();
deltaTime = clock.restart(); // get elapsed time
if (deltaTime > 0.25) { deltaTime = 0.25; } // drop frame guard
accumulator += deltaTime;
while (accumulator >= timeStep) {
// spritePosBefore = sprite.getPosition();
accumulator -= timeStep;
// sprite.move(velocity * timeStep, 0);
// spritePosAfter = sprite.getPosition();
}
if (accumulator > timeStep) { alpha = accumulator / timeStep; } else { alpha = 1.0; }
// sprite.setPosition(Vector2f(spritePosBefore * (1 - alpha) + spritePosAfter * alpha));
clear();
draw(sprite);
display();
}
现在,一切看起来都不错。我有固定的物理时间步长,在物理更新后尽可能画画,并在两个位置之间插值。它应该完美无缺,但我仍然可以看到精灵卡顿,甚至偶尔回溯一个像素。为什么会这样?我的代码有问题吗?我花了最后两天的时间试图理解游戏循环,这将确保我完美无瑕的动作,但似乎它不像我想象的那样有效。知道有什么可以改进的吗?
您应该删除 if 语句并始终计算 alpha; if 语句永远不会执行,因为在退出 while 循环后条件始终为 false!
循环后,累加器将介于 0 和 timeStep 之间,因此您最终只需绘制最新位置而不是插值。
我不认为你这样做的方式一定是错误的,但它看起来有点过于复杂。我不完全明白你想做什么,所以我只是要分享我在 SFML 应用程序中实现"固定时间步长"的方式。
以下是最简单的方法,对于大多数应用程序来说"足够好"。不过,这不是最精确的(测量时间和实时时间之间可能会有一点误差(:
sf::Clock clock;
sf::Event event;
while (window_.isOpen()) {
while (window_.pollEvent(event)) {}
if (clock.getElapsedTime().asSeconds() > FLT_FIXED_TIME_STEP) {
clock.restart();
update(FLT_FIXED_TIME_STEP);
}
render();
}
如果你真的需要精度,你可以添加一个浮点变量来充当"缓冲区":
sf::Clock clock;
sf::Event event;
float timeBeforeNextStep = 0.f; // "buffer"
float timeDilation = 1.f; // Useful if you want to slow or speed up time ( <1 for slowmo, >1 for speedup)
while (window_.isOpen()) {
while (window_.pollEvent(event)) {}
timeBeforeNextStep -= clock.restart().asSeconds() * timeDilation;
if (timeBeforeNextStep < FLT_FIXED_TIME_STEP) {
timeBeforeNextStep += FLT_FIXED_TIME_STEP; // '+=', not '=' to make sure we don't lose any time.
update(FLT_FIXED_TIME_STEP);
// Rendering every time you update is not always the best solution, especially if you have a very small time step.
render();
}
}
您可能希望使用另一个缓冲区进行渲染(例如,如果要以正好 60 FPS 的速度运行(。
相关文章:
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- 计算每个节点的树高,帮助我解释这个代码解决方案
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- visual c++,如何获取解决方案目录中的代码
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- C++Matching Brackets 2解决方案不起作用
- 在 ubuntu3 上C++ goto 定义有什么解决方案吗16.04?
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的固定时间步长与增量时间和插值的解决方案是错误的吗?
- 无法在问题解决方案中执行输出逻辑
- 将使用太多的纹理插值器 - 带旋转的着色器
- 最大的回文产品 - 程序未运行,编写解决方案但无法理解问题
- gmock支持右值引用的解决方案
- 如何更好地使用 STL 和函子来获取滑动窗口最小值的解决方案
- 采用N个参数并返回N个值的高性能解决方案
- c++中按引用传递和按值传递之间重载歧义的实用解决方案
- 为std::function赋值抽象函数——为什么std::ref是一个解决方案
- 返回值复制问题(以改进调试时间)-- 这里的解决方案是什么?
- 类中成员初始值设定项和初始化列表之间的冲突解决方案