可增加时间的倒计时器算法

发布于 2024-08-28 01:19:32 字数 743 浏览 3 评论 0原文

我正在制作一个通用计时器,它具有从 0 开始计数或从某个数字开始倒数的功能。我还希望它允许用户添加和减去时间。除了计时器从某个数字倒计时以及用户从中添加或减去时间的情况之外,一切都很容易实现。

例如:(m_clock 是 SFML 的 Clock 的实例)

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    m_elapsedTime += m_clock.GetElapsedTime() - m_elapsedTime;
  } else {
    m_elapsedTime -= 
      m_elapsedTime - m_startingTime + m_clock.GetElapsedTime();
  }
  return m_elapsedTime;
}

为了更清楚一点,想象一下计时器从 100 开始倒计时。 10 秒后,上述函数将类似于 100 -= 100 - 100 + 10,等于 90。如果再过 20 秒后调用它,它将类似于 90 -= 90 - 100 + 30,等于 70

这适用于正常计数,但如果用户调用 AddTime() (只是 m_elapsedTime += arg ),则向后计数的算法会严重失败。

我知道我可以使用更多成员并跟踪以前的时间等来做到这一点,但我想知道我是否错过了一些非常明显的实现。我希望在单一操作中尽可能保持简单。

I'm making a general timer that has functionality to count up from 0 or count down from a certain number. I also want it to allow the user to add and subtract time. Everything is simple to implement except for the case in which the timer is counting down from some number, and the user adds or subtracts time from it.

For example: (m_clock is an instance of SFML's Clock)

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    m_elapsedTime += m_clock.GetElapsedTime() - m_elapsedTime;
  } else {
    m_elapsedTime -= 
      m_elapsedTime - m_startingTime + m_clock.GetElapsedTime();
  }
  return m_elapsedTime;
}

To be a bit more clear, imagine that the timer starts at 100 counting down. After 10 seconds, the above function would look like 100 -= 100 - 100 + 10 which equals 90. If it was called after 20 more seconds it would look like 90 -= 90 - 100 + 30 which equals 70.

This works for normal counting, but if the user calls AddTime() ( just m_elapsedTime += arg ) then the algorithm for backwards counting fails miserably.

I know that I can do this using more members and keeping track of previous times, etc. but I'm wondering whether I'm missing some implementation that is extremely obvious. I'd prefer to keep it as simple as possible in that single operation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

依 靠 2024-09-04 01:19:32

您的代码不必要地复杂。以下是等效的:

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    m_elapsedTime = m_clock.GetElapsedTime();
  } else {
    m_elapsedTime = m_startingTime - m_clock.GetElapsedTime();
  }
  return m_elapsedTime;
}

并希望说明为什么 AddTime() 不起作用:每次调用 GetElapsedTime() 时都会替换 m_elapsedTime。最简单的解决方案是分别跟踪添加/减少的时间并重新修改 GetElapsedTime() 因此:

float Timer::GetElapsedTime() {
  float elapsedTime = m_forward
                      ? m_clock.GetElapsedTime()
                      : m_startingTime - m_clock.GetElapsedTime();
  return elapsedTime + m_addedTime;
}

Your code is unnecessarily complex. The following is equivalent:

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    m_elapsedTime = m_clock.GetElapsedTime();
  } else {
    m_elapsedTime = m_startingTime - m_clock.GetElapsedTime();
  }
  return m_elapsedTime;
}

and hopefully illustrates why AddTime() doesn't work: m_elapsedTime is being replaced on every call to GetElapsedTime(). The simplest solution is track added/subtracted time separately and rework GetElapsedTime() thus:

float Timer::GetElapsedTime() {
  float elapsedTime = m_forward
                      ? m_clock.GetElapsedTime()
                      : m_startingTime - m_clock.GetElapsedTime();
  return elapsedTime + m_addedTime;
}
孤檠 2024-09-04 01:19:32

如果您想增加剩余时间,可以通过减少已用时间来模拟。

您的算术表达式比需要的更复杂:m_elapsedTime += m_clock.GetElapsedTime() - m_elapsedTime 相当于 m_elapsedTime = m_clock.GetElapsedTime(),并且 m_elapsedTime -= m_elapsedTime - m_startingTime + m_clock.GetElapsedTime() 相当于 m_elapsedTime = m_startingTime - m_clock.GetElapsedTime()`。

至此,问题就清楚了:m_elapsedTime的旧值永远不会影响后续的结果。我会考虑添加一个 offset 字段来处理计时器起始值的任何更改。此时,Timer:GetElapsedTime 可能如下:

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    return offset + m_clock.GetElapsedTime();
  } else {
    return offset - m_clock.GetElapsedTime();
  }
}

其中,向上计数的偏移量从 0 开始,向下计数的起始值。确保并观察 AddTime() 中更新偏移量的迹象

If you want to increase the time remaining, you can simulate that by decreasing the amount of time elapsed.

Your arithmetic expressions are more complex than they need to be: m_elapsedTime += m_clock.GetElapsedTime() - m_elapsedTime is equivalent to m_elapsedTime = m_clock.GetElapsedTime(), and m_elapsedTime -= m_elapsedTime - m_startingTime + m_clock.GetElapsedTime() is equivalent to m_elapsedTime = m_startingTime - m_clock.GetElapsedTime()`.

At this point, the problem is clear: the old value of m_elapsedTime never affects the subsequent result. I would consider adding in an offset field to handle any changes to the starting value of the timer. At this point, Timer:GetElapsedTime could just be the following:

float Timer::GetElapsedTime() {
  if ( m_forward ) {
    return offset + m_clock.GetElapsedTime();
  } else {
    return offset - m_clock.GetElapsedTime();
  }
}

where offset starts at 0 for a count-up and the start value for a count-down. Make sure and watch your signs for updating offset in AddTime()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文