Алгоритм таймера обратного отсчета, который может добавить на время - PullRequest
2 голосов
/ 05 апреля 2010

Я делаю общий таймер, который имеет функцию для отсчета от 0 или отсчета с определенного числа. Я также хочу, чтобы позволить пользователю добавлять и вычитать время. Все просто реализовать, за исключением случая, когда таймер отсчитывает от некоторого числа, и пользователь добавляет или вычитает время из него.

Например: (m_clock - это экземпляр часов SFML)

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), тогда алгоритм обратного отсчета терпит неудачу.

Я знаю, что могу сделать это, используя больше участников и отслеживая предыдущее время и т. Д., Но мне интересно, упускаю ли я какую-то реализацию, которая является чрезвычайно очевидной. Я бы предпочел сделать это как можно более простым в этой единственной операции.

Ответы [ 2 ]

3 голосов
/ 05 апреля 2010

Ваш код излишне сложен. Следующее эквивалентно:

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

и, надеюсь, иллюстрирует, почему AddTime() не работает: m_elapsedTime заменяется при каждом вызове GetElapsedTime() Самое простое решение - отслеживать добавленное / вычитаемое время отдельно и переработать GetElapsedTime() таким образом:

float Timer::GetElapsedTime() {
  float elapsedTime = m_forward
                      ? m_clock.GetElapsedTime()
                      : m_startingTime - m_clock.GetElapsedTime();
  return elapsedTime + m_addedTime;
}
1 голос
/ 05 апреля 2010

Если вы хотите увеличить оставшееся время, вы можете смоделировать это на , уменьшив количество прошедшего времени.

Ваши арифметические выражения сложнее, чем должны быть: 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()

...