引入可变时间步长很麻烦
Trouble introducing a variable timestep
我目前在大学学习计算机游戏编程,正在用c++创建一个物理引擎。
我被要求通过GetTickCount()方法引入一个时间步进,尽管不准确,因为它适合当前深度,我们要进入时间步进
我的问题是,现在我已经引入了基于时间步长的运动,已经绘制到屏幕上的对象通过更新功能的两个不同的覆盖似乎不起作用。
通过在代码中添加断点,看起来好像mElapsedTime似乎没有传递任何值,我被难住了。
抱歉,如果这篇文章太啰嗦或有些跑题,我试图提供尽可能多的背景,这是我的第一篇文章,任何帮助都是感激的。
(frameStartTime参数只是获取帧更新和绘制之前的滴答计数)
编辑:float类型的失效时间,以便在更新粒子类时更容易乘法(例如pos.x = velocity)。x * timeStep),这就是从unsigned long转换为float的原因,它仍然是多余的吗?
void Simulation::gameLoopDelay(DWORD frameStartTime)
{
DWORD presetFrameInterval = 16;
DWORD frameProcessingTime = GetTickCount() - frameStartTime;
if (frameProcessingTime < presetFrameInterval)
{
Sleep(presetFrameInterval - frameProcessingTime);
}
mElapsedTime = (float)frameProcessingTime / 1000.0f;
}
我不是绝对确定(因为您没有提供足够的信息),但我看到的第一个问题是您做mElapsedTime = (float)frameProcessingTime / 1000.0f;
而不考虑Sleep(...)
。换句话说,你忘了把睡眠考虑在内。要做到这一点,您必须在调用Sleep(...)
后重新获取GetTickCount()
。但即使这样,你的代码也会变得过于样板化,容易出错。
通过编写小的、灵活的、可重用的类来处理你的问题,这些类只做简单的任务:
class Stopwatch {
public:
Stopwatch(): _start(0), _elapsed(0), _running(false) {}
void
start() {
if (_running)
return;
_running = true;
_start = GetTickCount();
}
void
stop() {
if (!_running)
return;
_elapsed += GetTickCount() - _start;
_running = false;
}
void
reset() {
_running = false;
_elapsed = 0;
}
void
restart() {
_running = true;
_elapsed = 0;
_start = GetTickCount();
}
bool
isRunning() const {
return _running;
}
DWORD
elapsed() const {
return _running ? _elapsed + (GetTickCount() - _start) : _elapsed);
}
bool
hasExpired(DWORD interval) const {
return elapsed() > interval;
}
private:
DWORD _start;
DWORD _elapsed;
bool _running;
};
如何利用这个类来满足你的需要是很简单的。
其次,我真的不明白你为什么使用Sleep
。我最后一次看到帧延迟的例子是在5年前的一些关于编写玩具游戏的蹩脚教程中。这些内容在老游戏中非常流行,但在现代游戏中却没有意义。当然,如果这是你作业的要求,那么我道歉,但这句话仍然适用。
最后,我想从我自己的实时可视化经验中给你一些额外的建议。永远不要使用GetTickCount
或其他Windows API(或Linux API,无关)程序员中流行的原始工具编写依赖于时间的代码,因为它再次散发出创建玩具游戏的过时教程的味道。
另一个,库- Boost。单位-这是一个必须编写稳定和准确的物理引擎。这个库为单位(力、质量、速度、加速度等)和各种单位系统模型(例如SI或CGS)的数量提供类型安全支持。它基于模板元编程,因此不会产生运行时开销。
再一次,我理解你的任务可能不允许这样的事情。但是,我相信我在这里提到的一切在将来对你都是有价值的。顺便说一下,这是一个很好的例子,说明为了能够解决现实生活中的问题,你应该比大学作业了解更多。如果你还需要更多的帮助,特别是你的问题-我需要更多的信息。例如,首先向我们展示游戏循环的全部代码。
我认为,基本上,你需要改变你的代码:
void Simulation::gameLoopDelay(DWORD frameStartTime)
{
DWORD presetFrameInterval = 16;
DWORD frameProcessingTime = GetTickCount() - frameStartTime;
if (frameProcessingTime < presetFrameInterval)
{
Sleep(presetFrameInterval - frameProcessingTime);
}
frameProcessingTime = GetTickCount() - frameStartTime;
mElapsedTime = (float)frameProcessingTime / 1000.0f;
}
这不是最建议的方法,因为这里的Sleep
可能会锁定整个线程。最好是在分数时间内完成帧,但我认为这将修复您的代码。
- C++为构建时间获取QDateTime的可靠方法
- 从持续时间构造std::chrono::system_clock::time_point
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- while循环中while循环的时间复杂度是多少
- 使用简单类型列表实现的指数编译时间.为什么
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 在已经使用Git的情况下减少编译时间
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 从文本文件中读取时钟时间和事件时间并进行处理
- 具有未知值时的时间复杂性
- 如何减少花费的时间
- C++在变量给定的指定时间内关闭电脑
- rcpp函数中的清理时间很长
- C++:floor unix时间戳到UTC月份
- 如何在c++中录制具有精确帧时间戳的视频
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- KMP算法和LPS表构造的运行时间
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 引入可变时间步长很麻烦