Hello everyone,
I'm not sure if this is the right area to place this in as I'm not new to C++ or game design, however in the past I had the framework handle my FPS, but now I'm doing it myself, and would be new to implementation of a fixed game speed, with rendering FPS as fast as possible. I have experience in using Variable Time-steps, but I'm not a fan of them. I've also set up a fixed FPS with logic and draws under the same hood, as well as a grid system for movement prior while letting the framework handle time. If this is in the wrong area please feel free to move it.
I've been spending sometime on researching game loops but wanted to be sure I understand what makes everything tick. Personally, it's not enough for me to have something work unless I understand why it works the way it does.
I'm using Dewitters Game Loop - Constant Game Speed independent of Variable FPS
http://www.koonsolo.com/news/dewitters-gameloop/
My current code is below and I wanted to make sure I understand what is going on.
// Timer for 30 INPUT LOGIC UPDATES PER SECOND
const float ticksPerSecond = 30.f; // Updates per second
const float skipTicks = 1000.f / ticksPerSecond; // This would be 33.33333333333333
const int maxFrameSkip = 5; // Force draw if looping more than 5 times
sf::Clock mainClock;
double nextTick = mainClock.restart().asMilliseconds(); // Set nextTick to = current time elapsed in Milliseconds (reset first)
int loops = 0;
float interpolation = 0.f;
while (mainWindow.isOpen()) {
// Event Processing
sf::Event event;
while (mainWindow.pollEvent(event)) {
// Closing Window
if (event.type == sf::Event::Closed) {
mainWindow.close();
}
}
loops = 0;
while (mainClock.getElapsedTime().asMilliseconds() > nextTick && loops < maxFrameSkip) {
// Updates - LOGIC
Input()
Logic();
nextTick += skipTicks;
loops++;
}
// Clear Window
mainWindow.clear();
// Draw to Window
mainWindow.draw(SOMETHING);
// Display
mainWindow.display();
std::cout << "Draw - loops: " << loops << std::endl;
// Just to see if updates are at 30 FPS
std::cout << "UPDATE FPS: " << (mainClock.getElapsedTime().asMilliseconds() / nextTick) * 30 << std::endl;
}
My understanding is that I'm using ticksPerSecond to dictate that I only want my logic and updates to cycle through a maximum of 30 times per second.
skipTicks = 1000 / 30; would be the amount of time per update in milliseconds.
I then have maxFrameSkip = 5 so if loop exceeds this amount it will not loop through logic, but just render and reset the counter.
mainClock is for tracking the amount of time, and nextTick will just equal mainClock in milliseconds.
loops is just for tracking if we hit the 5+, and interpolation isn't a problem yet as I haven't gone that far yet.
The main thing I need to understand is the loop, and how it works.
My loop starts by setting the loop counter to 0, and then checking to see if the elapsed time is greater than nextTick, as well as seeing if loops is less than our maxFrameSkip variable.
I'm assuming it's supposed to work like this. The loop will make sure to hit once per every 0.03333 seconds, and render as fast as possible outside of this. If the loop starts and the game time is 20 ms, and our nextTick is 33.333 ms it will draw until the timer hits a number greater than 33.3333 ms. Let's suppose the game timer hits 35 ms it will loop through making nextTick 66.6666 ms, then render as fast as possible until the game timer is greater than nextTick, ect...
If the loop takes too long it will make the game timer much higher than nextTick which could cause the loop to cycle through several times and not draw, this is why we have the loop counter and maxFrameSkip, so if it hits a number greater than 5 it forces the draw while trying to catch up. I'm confused on what would happen if the game was hanging several times, couldn't it create an impossible scenario that wouldn't be able to catch up? Wouldn't it be a good idea to track if we hit our loop at 5 counts x amount of times, to make nextTick = our game time + skipTick to reset?
Also, is this a correct way to messure the update time for the loop?
std::cout << "UPDATE FPS: " << (mainClock.getElapsedTime().asMilliseconds() / nextTick) * 30 << std::endl;
Is my game loop correct in keeping event input outside of the loop, and only having real-time input (moving game toons around) + logic within? Then drawing outside as the final step?
I wanted to make sure I have a good understanding of what is going on here before I move forward. Thank you!
EDIT: I set up interpolation and it's moving very smooth. Thanks for all the help!