Контроль последовательности спрайтов через DeltaTime

Ранее в моем основном цикле игры время было установлено на уровне 60 кадров в секунду и соответствующей задержки для временной задержки.

Последовательность Спрайта была анимирована следующим образом:

<pre>
if(++ciclos > 10){
   siguienteSprite++;
   ciclos = 0;
}
</pre>

Учитывая, что я использую Smooth Motion с DeltaTime, поэтому я исключил задержку из основного цикла; Делая это, циклы анимации спрайтов быстрее, и не только это, но также и время между каждой последовательностью меняется.

Кто-то может мне помочь, только с логикой этой проблемы, заранее спасибо.:)

1 ответ

Решение

delay в основном цикле не очень хороший способ для этого (так как он не учитывает время, затрачиваемое другими вещами в основном цикле). Когда вы удаляете задержку, тогда скорость увеличивается и изменяется больше, потому что другие элементы в синхронизации основного цикла более значительны и обычно не постоянны по многим причинам, таким как:

  • Зернистость ОС
  • синхронизация с картой / драйвером gfx
  • непостоянное время обработки

Есть больше способов, как справиться с этим:

  1. измерять время

    <pre>
    t1=get_actual_time();
    while (t1-t0>=animation_T)
     {
     siguienteSprite++;
     t0+=animation_T;
     }
    // t0=t1; // this is optional and change the timing properties a bit
    </pre>
    

    где t0 некоторая глобальная переменная, содержащая "последнее" измеренное время изменения спрайта. t1 фактическое время и animation_T постоянная времени между изменениями анимации. Для измерения времени вам нужно использовать OS API как PerformanceCounter на окнах или RDTSC в asm или любой другой, вы получили под рукой, но с достаточно маленьким разрешением.

  2. Таймер ОС

    просто увеличить siguienteSprite в каком-то таймере с animation_T интервал. Это просто, но таймеры ОС не точны и обычно составляют около 1 мс или более + степень детализации ОС (аналогично Sleep точность).

  3. Таймер потока

    Вы можете создать один поток для целей синхронизации, например, что-то вроде этого:

    for (;!threads_stop;)
     {
     Delay(animation_T); // or Sleep()
     siguienteSprite++;
     }
    

    Не забудь этого siguienteSprite должно быть volatile и буферизуется во время рендеринга, чтобы избежать мерцания и / или ошибок нарушения доступа. Этот подход немного более точен (если только у вас нет одноядерного процессора).

    Вы также можете увеличить некоторую переменную времени и использовать ее в качестве фактического времени в своем приложении с любым разрешением, которое хотите. Но будьте осторожны, если delay не возвращает управление процессором в ОС, тогда этот подход будет использовать ваш процессор для 100%/CPU_cores, Для этого есть средство, которое заменяет ваш delay с этим:

    Sleep(0.9*animation_T);
    for (;;)
     {
     t1=get_actual_time();
     if (t1-t0>=animation_T)
      {
      siguienteSprite++;
      t0=t1;
      break;
      }
    

Если вы используете измеренное время, вы должны справиться с переполнением (t1<t0) потому что любой счетчик будет переполнен со временем. Например, используя 32-битную часть RDTSC на 3.2 GHz Ядро процессора будет переполняться каждый 2^32/3.2e9 = 1.342 sec так что это реальная возможность. Если у меня хорошо работает память, то счетчики производительности в Windows обычно бегают 3.5 MHz на старых системах ОС и около 60-120 MHz на более новых (по крайней мере, в прошлый раз, когда я проверяю), и они 64-битные, так что переполнения не являются большой проблемой (если вы не запускаете 24/7). Также в случае использования RDTSC вы должны установить привязку процесса / потока к одному ядру ЦП, чтобы избежать проблем с синхронизацией на многоядерных ЦП.

Я выполнил свою часть сравнительного анализа и усовершенствовал синхронизацию с высоким разрешением на низком уровне за эти годы, поэтому вот несколько связанных с ними QA:


неправильные измерения тактового цикла с rdtsc - ОС Granularity
Измерение задержек кэша - измерение частоты процессора
Оценка размера кэша в вашей системе? - PerformanceCounter пример
Вопросы по измерению времени с использованием тактовой частоты процессора - PIT как альтернативного источника синхронизации

Другие вопросы по тегам