(In the beginning, sorry for my english
)
Hi everybody. I know that there are some similar questions about laggy fixed time step loop on SFML forum, but I didn't find answer.
Recently I remade my loop code, because previous fixed time step loop on every computer behave differently, on slower computer game was slower, on faster computer game was faster. It was something like that:
const float FPS=100.0f;
RenderWindow window;
Clock clock;
Time time;
while(window.isOpen())
{
if(time.asSeconds()>(1.0f/FPS))
{
update();
clock.restart();
time=Time::Zero;
}
display();
time=clock.getElapsedTime();
}
So I was searching better fixed time step loop on the internet. I found some good articles, for example:
I've decided to the last article. It's in polish language, but it doesn't matter. There is (for me) the best and the clearest loop:
float dt = 0.0f; //time since last update
float lastUpdateTime = GetCurrentTime(); //last update time
//exemplary GetCurrenTime() function gets
//current time from system (in SFML it's just getElapsedTime())
float accumulator = 0.0f;
const float TIME_STEP = 0.03; //time step and frame duration
//physics in seconds; here 30 miliseconds,
//about 30 updates per second
const float MAX_ACCUMULATED_TIME = 1.0; //max time gathered in single
//main loop circuit
while(true)
{
dt = GetCurrentTime() - lastUpdateTime; //calculation of the time since the last frame
lastUpdate += dt; //substitution
dt = std::max(0, dt); //we're making sure that dt>=0
accumulator += dt;
accumulator = clamp(accumulator, 0, MAX_ACCUMULATED_TIME); //we prevent
//too many updates in a given loop
//cycle
GrabInput(); //<-- keyboard, mouse, network etc. events
while(accumulator > TIME_STEP)
{
UpdateGame(TIME_STEP); //<-- physics and game logic update
accumulator -= TIME_STEP;
}
RenderGame(); //<-- display current game state on screen
}
//clamp function
template <typename T>
T clamp(const T& what, const T& a, const T& b)
{
return std::min(b, std::max(what, a));
}
In SFML implementation it looks like this:
float dt = 0.0f; //time since last update
float lastUpdateTime = 0.f;
float accumulator = 0.0f;
const float TIME_STEP = 0.03; //I initialise this variable differently: const float TIME_STEP=1.f/60.f for 60 FPS
const float MAX_ACCUMULATED_TIME = 1.0;
while(true)
{
dt = clock.getElapsedTime().asSeconds() - lastUpdateTime; //clock is restarting in constructor
lastUpdate += dt;
dt = std::max(0, dt);
accumulator += dt;
accumulator = clamp(accumulator, 0, MAX_ACCUMULATED_TIME);
GrabInput();
while(accumulator > TIME_STEP)
{
UpdateGame(TIME_STEP);
accumulator -= TIME_STEP;
}
RenderGame();
}
OK, this loop is working same on different computers, but now there is a new problem. My loop is lagging. It's not smooth as previous loop. It's not lagging all time, but it's noticeable. I tried to replace TIME_STEP (in UpdateGame function) to accumulator, deltaTime or lastUpdateTime, but as expected it didn't help. I tried to change timeStep and it didn't help too. I was experimenting with setFramerateLimit() and setVerticalSyncEnabled(), no changes. I think everything is calculated correctly, but to make sure I checked variables values:
...
while(accumulator > TIME_STEP)
{
UpdateGame(TIME_STEP);
cout << "Delta time: " << dt << endl;
cout << "Last update time: " << lastUpdateTime << endl;
cout << "Accumulator (before subtract): " << accumulator << endl;
accumulator -= TIME_STEP;
cout << "Accumulator (after subtract): " << accumulator << endl;
cout << "Time step: " << TIME_STEP << endl;
cout << "Max accumulated time: " << MAX_ACCUMULATED_TIME << endl;
cout << "------------------------------------------------------" << endl;
}
...
Here is output (random sample):
------------------------------------------------------
Delta time: 0.0154901
Last update time: 5.5339
Accumulator (before subtract): 0.0172362
Accumulator (after subtract): 0.0005695
Time step: 0.0166667
Max accumulated time: 1
------------------------------------------------------In deWiTTERS article in the last loop example was interpolation, which smooths everything, but I'm not sure I need it. I think there is other solution. I don't know what's wrong with this code.
Thanks for help.