我正在使用std :: chrono编写标准的游戏循环。我需要将float传递给我的render方法,该方法代表到下一帧的距离。要使用chrono :: duration的count()方法计算数字,因此我需要将两个持续时间转换为相同的比率。
void engine::run() {
using namespace std::chrono;
using updates = duration<steady_clock::rep, std::ratio<1, 40>>;
using common = std::common_type<updates, steady_clock::duration>::type;
constexpr updates time_per_update{1};
auto previous = steady_clock::now();
auto lag = steady_clock::duration::zero();
while (!quit) {
auto now = steady_clock::now();
auto delta = now - previous;
previous = now;
lag += delta;
while (lag >= time_per_update) {
lag -= time_per_update;
update(time_per_update);
}
render(common{lag}.count() / static_cast<double>(common{time_per_update}.count()));
}
}
如果我将'updates'中的比率更改为41,则在减法时会出现编译错误,因为1/41秒的时间无法精确转换为stable_clock :: duration。但是,当我将代码重写为此时,它可以正常编译:
void engine::run() {
using namespace std::chrono;
using updates = duration<steady_clock::rep, std::ratio<1, 41>>;
using common = std::common_type<updates, steady_clock::duration>::type;
constexpr common time_per_update{updates{1}};
auto previous = steady_clock::now();
common lag = steady_clock::duration::zero();
while (!quit) {
auto now = steady_clock::now();
auto delta = now - previous;
previous = now;
lag += delta;
while (lag >= time_per_update) {
lag -= time_per_update;
update(time_per_update);
}
render(lag.count() / static_cast<double>(time_per_update.count()));
}
}
我的印象是,在减法期间隐式发生了向common_type的转换。我想念什么?有更好的方法吗?
答案 0 :(得分:0)
为澄清起见,这是发生错误的代码行:
lag -= time_per_update;
test.cpp:27:11: error: no viable overloaded '-='
lag -= time_per_update;
~~~ ^ ~~~~~~~~~~~~~~~
我的印象是,在减法期间隐式发生了向common_type的转换。
您是正确的,但不完全正确。
binary 减法运算符返回两个参数的common_type
:
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type
operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
但是-=
运算符必须等效于:
lag = lag - delta;
如果result
的{{1}}不能隐式转换为lag - delta
的类型,那么您就遇到了问题(例如您的示例)。
将lag
的类型更改为lag
是正确的解决方法:
common
这是另一种方法。两者之间的选择在风格上是
common lag = steady_clock::duration::zero();
最后,就像个人一样,我想尽量减少(如果不能消除)对auto lag = steady_clock::duration::zero() + updates{0};
的使用,因为这相当于.count()
从reinterpret_cast
到{{1} }(或标量)。在您的示例中,这并不难做到,并且不会降低效率。
首先添加与duration
等效的内容,并使用integral
作为表示形式:
common
然后,您只需将double
转换为using dcommon = duration<double, common::period>;
并将其除以lag
即可得到比率:
dcommon
最后,您还可以考虑另一种样式上的变化:首先将time_per_update
表示为基于render(dcommon{lag} / time_per_update);
的前端:
lag
现在,您对double
的呼叫更加简单:
auto lag = steady_clock::duration::zero() + updates{0} + duration<double>{0};
甚至不再需要render
和render(lag / time_per_update);
(您可以删除它们)。