Я упоминал об этом раньше в других темах, связанных с игрой. Как всегда, следуйте советам Гленна Фидлера в его серии Game Physics
То, что вы хотите сделать, это использовать постоянный временной шаг , который вы получаете, накапливая дельты времени. Если вы хотите 33 обновления в секунду, то ваш постоянный временной шаг должен быть 1/33. Вы также можете назвать это частота обновления . Вы также должны отделить игровую логику от рендеринга, поскольку они не принадлежат друг другу. Вы хотите иметь возможность использовать низкую частоту обновления при рендеринге так быстро, как позволяет машина. Вот пример кода:
running = true;
unsigned int t_accum=0,lt=0,ct=0;
while(running){
while(SDL_PollEvent(&event)){
switch(event.type){
...
}
}
ct = SDL_GetTicks();
t_accum += ct - lt;
lt = ct;
while(t_accum >= timestep){
t += timestep; /* this is our actual time, in milliseconds. */
t_accum -= timestep;
for(std::vector<Entity>::iterator en = entities.begin(); en != entities.end(); ++en){
integrate(en, (float)t * 0.001f, timestep);
}
}
/* This should really be in a separate thread, synchronized with a mutex */
std::vector<Entity> tmpEntities(entities.size());
for(int i=0; i<entities.size(); ++i){
float alpha = (float)t_accum / (float)timestep;
tmpEntities[i] = interpolateState(entities[i].lastState, alpha, entities[i].currentState, 1.0f - alpha);
}
Render(tmpEntities);
}
Это касается как недостаточной, так и избыточной выборки. Если вы используете целочисленную арифметику, как здесь, ваша физика игры должна быть почти на 100% детерминированной, независимо от того, насколько медленной или быстрой будет машина. Это преимущество увеличения времени через фиксированные интервалы времени. Состояние, используемое для рендеринга, рассчитывается путем интерполяции между предыдущим и текущим состояниями, где оставшееся значение внутри временного аккумулятора используется в качестве коэффициента интерполяции. Это гарантирует, что рендеринг будет плавным, независимо от того, насколько велик временной шаг.