引入可变时间步长时遇到问题 我现在在大学里做计算机游戏编程,在C++中创建物理引擎的过程。

引入可变时间步长时遇到问题 我现在在大学里做计算机游戏编程,在C++中创建物理引擎的过程。,c++,timer,C++,Timer,我被要求通过GetTickCount()方法引入一个timestep,尽管有不准确的地方,因为它适合我们将要进入时间步进的当前深度 我的问题是,现在我引入了基于timestep的移动,通过更新函数的两个不同重写绘制到屏幕上的对象似乎不起作用 通过在代码中添加断点,看起来mElapsedTime似乎没有传递任何值,我被难住了 抱歉,如果这篇文章太罗嗦或者有些是离题的,我会尽可能提供更多的上下文,这是我的第一篇文章,任何帮助都将不胜感激 (frameStartTime参数仅在更新和绘制帧之前进行勾号

我被要求通过GetTickCount()方法引入一个timestep,尽管有不准确的地方,因为它适合我们将要进入时间步进的当前深度

我的问题是,现在我引入了基于timestep的移动,通过更新函数的两个不同重写绘制到屏幕上的对象似乎不起作用

通过在代码中添加断点,看起来mElapsedTime似乎没有传递任何值,我被难住了

抱歉,如果这篇文章太罗嗦或者有些是离题的,我会尽可能提供更多的上下文,这是我的第一篇文章,任何帮助都将不胜感激

(frameStartTime参数仅在更新和绘制帧之前进行勾号计数)

编辑:浮点类型的mElapsed time,为了更容易在粒子类更新中乘法(例如,pos.x=velocity.x*timeStep),这就是将无符号长型转换为浮点型的原因,它是否仍然是多余的

void Simulation::gameLoopDelay(DWORD frameStartTime)
{
    DWORD presetFrameInterval = 16;
    DWORD frameProcessingTime = GetTickCount() - frameStartTime;

    if (frameProcessingTime < presetFrameInterval)
    {
        Sleep(presetFrameInterval - frameProcessingTime);
    }

    mElapsedTime = (float)frameProcessingTime / 1000.0f;
}
void模拟::gameLoopDelay(DWORD frameStartTime)
{
DWORD预设帧间隔=16;
DWORD frameProcessingTime=GetTickCount()-frameStartTime;
if(帧处理时间<预设帧间隔)
{
睡眠(预设帧间隔-帧处理时间);
}
mElapsedTime=(浮点)帧处理时间/1000.0f;
}

我认为,基本上,您需要将代码更改为:

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;
}
void模拟::gameLoopDelay(DWORD frameStartTime)
{
DWORD预设帧间隔=16;
DWORD frameProcessingTime=GetTickCount()-frameStartTime;
if(帧处理时间<预设帧间隔)
{
睡眠(预设帧间隔-帧处理时间);
}
frameProcessingTime=GetTickCount()-frameStartTime;
mElapsedTime=(浮点)帧处理时间/1000.0f;
}
这不是最好的方法,因为这里的
Sleep
可能会锁定整个线程。只在小数点时间执行帧可能更好,但我认为这将修复您的代码。

我不是绝对确定(因为您没有提供足够的信息),但我看到的第一个问题是您执行
mElapsedTime=(float)frameProcessingTime/1000.0f不考虑睡眠(…)
。换句话说,你忘了考虑睡觉。为此,您必须在调用
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;
};
如何利用这个类满足您的需求是很简单的

其次,我真的不明白你为什么要使用
睡眠
。我最后一次看到帧延迟的例子是大约5年前在一些关于编写玩具游戏的蹩脚教程中。这种东西在旧游戏中非常流行,但在现代游戏中却毫无意义。当然,如果这是你的作业要求,那么我道歉,但这句话仍然适用

最后,我想从我自己的实时可视化经验中给大家一些额外的建议决不使用诸如
GetTickCount
之类的原始工具或Windows API(或Linux API,无所谓)程序员中其他流行的垃圾编写与时间相关的代码,因为它再次散发出创建玩具游戏的过时教程的味道

你会问,那该用什么呢?现在我们很幸运,因为有设计良好、可靠的跨平台库,比如。你可能应该熟悉它,但是如果你不熟悉,你肯定应该熟悉。对于您的特殊问题,有一个模块经过精心设计,可以正确地处理时间。我在几个涉及实时渲染的项目中使用过它,我不得不承认它非常健壮,值得学习

另一个是库,它是编写稳定而准确的物理引擎所必须的。该库为各种单位系统模型(例如SI或CGS)的单位(力、质量、速度、加速度等)和数量提供类型安全支持。它基于模板元编程,因此不会产生运行时开销

再一次,我明白你的任务可能不允许这样的事情发生。然而,我相信我在这里提到的一切对你将来都是有价值的。顺便说一句,这是一个很好的例子,说明你应该比大学作业了解更多,才能解决现实生活中的问题


如果你还需要更多的帮助,特别是在你的问题上-我需要更多的信息。例如,首先向我们展示游戏循环的全部代码。

这是一个很好的第一个问题。我有几点要注意的是,您的
presetFrameInterval
应该是一个常量,并且最后一行中对
float
的转换是多余的。
mElapsedTime
a
float
?你有没有办法把相关的代码浓缩成一个完整的样本,只包含完全相关的代码?你自己试着调试这个问题真是太好了。然而,仅凭这段代码片段,我们无法告诉您多少。这里没有什么明显的错误。我看到的最直接的潜在错误是假设睡眠后经过的时间与传递到sleep()的请求间隔是准确的。情况肯定不会如此。你不知道你从睡梦中醒来后有多长时间没有重新绘制GetTickCount()。(和问题的道具;它比大多数第一个问题,甚至非第一个问题要好得多。你已经试着先分析和帮助自己,这是巨大的)。注意,在真实游戏中,你通常希望避免这种帧延迟的东西。只要开始做t