无法引入变量时间步长

时间:2013-03-19 18:13:04

标签: c++ timer

我目前正在大学从事计算机游戏编程,在使用C ++创建物理引擎的过程中。

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

我的问题是,现在我已经介绍了基于时间步长的移动,通过两个不同的更新函数覆盖来绘制屏幕的对象似乎不起作用。

通过在代码中添加断点,看起来好像mElapsedTime似乎没有传递任何值而且我很难过。

很抱歉,如果这篇文章过于冗长或有些偏离主题,我试图提供尽可能多的上下文,这是我的第一篇文章,感谢任何帮助。

(frameStartTime参数只是在更新和绘制帧之前采用滴答计数)

编辑:m float类型的时间,以便在粒子类的更新中更容易相乘(例如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;
}

2 个答案:

答案 0 :(得分:1)

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

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这里可能会锁定整个线程。

,这可能会更好地在一个小时间内完成框架,但我认为这会修复你的代码。

答案 1 :(得分:1)

我不是很确定(因为你没有提供足够的信息),但我看到的第一个问题是mElapsedTime = (float)frameProcessingTime / 1000.0f;无论Sleep(...)如何。换句话说,你忘了考虑睡觉。为此,您必须在致电GetTickCount()后重新抓取Sleep(...)。但即便如此,您的代码也会过于样板化且容易出错。

通过编写执行简单任务的小型,灵活且可重用的类来开始解决您的问题:

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。你可能应该熟悉它,但如果你不熟悉 - 你绝对应该这样做。对于您的特定问题,有一个模块Boost.Chrono经过精心设计,可以正常使用时间。我在几个涉及实时渲染的项目中使用过它,我不得不承认它非常强大且值得学习。

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

再次,我明白你的作业可能不允许这样的东西。但是,我相信我在这里提到的所有内容对你来说都很有价值。顺便说一句,这是一个很好的例子,你应该知道你应该知道多少能够解决现实问题的大学任务。

如果您仍需要更多关于问题的帮助 - 我需要更多信息。例如,首先向我们展示游戏循环的整个代码。