1
Window / Re: Is SetFramerateLimit() actually useful? [in respect to its issues]
« on: May 07, 2019, 10:03:31 pm »
So for your first two paragraphs. I am aware of why limiting is desirable. While I have only been using SFML for about a year now, I had been using SDL for two years prior (both with its internal renderer and OpenGL). SDL seems to keep its 60fps reliably, while SFML does not. (example code at the bottom of post, to show that I wasn't spinning hot to achieve this)
For context I am working in game development.
I give the player the option to enable v-sync, the frame rate limiter, or neither. That is their choice to make (although I do prevent both from being used concurrently, because that would be plain bad). In my case the player has control over what frame rate limit they wish to use. Typically players will set the frame rate limit to that of their monitors refresh rate. They do this to combat tearing. While a good 60fps limiter won't stop tearing, it will greatly reduce its visual appearance without the drawbacks of vsync. Hence many gamers consider it to be a more desirable option than vsync.
Since my game runs anywhere from 20fps to "infinite fps", movement is interpolated based upon frame timings. Obviously it runs smooth without limiting, it also runs smooth with vsync enabled (60fps on my monitor), but with the limiter enabled at 60fps it gets visibly choppy.
Now while v-sync is an option, v-sync isn't perfect, since it adds a slight delay to the rendering, which some people find uncomfortable to use, especially with regards to mouse movement. Of course, I could use the native windows mouse pointer, but then UI collision detection is one frame behind the current mouse location on screen, leading to clicks being registered in the wrong place. Which can be quite frustrating.
Hence, I find myself wondering if SFML's frame rate limiter is currently fit for purpose? However, I must admit, when I made the OP, I had mistakenly assumed that SFML would have a similar feature to SDL where you can tell it to sleep, upon further inspection it does not seem to. As such there isn't currently any "just works" way to do better.
So my guess would be that the only real solution is to manually time how long SFML waited for on the last frame. Then set the FPS limit each frame to purposefully undershoot slightly, and then spin hot in a while loop until the correct time is achieved.
Its hardly the end of the world, but it doesn't feel that elegant (or simple) either xD
For context I am working in game development.
I give the player the option to enable v-sync, the frame rate limiter, or neither. That is their choice to make (although I do prevent both from being used concurrently, because that would be plain bad). In my case the player has control over what frame rate limit they wish to use. Typically players will set the frame rate limit to that of their monitors refresh rate. They do this to combat tearing. While a good 60fps limiter won't stop tearing, it will greatly reduce its visual appearance without the drawbacks of vsync. Hence many gamers consider it to be a more desirable option than vsync.
Since my game runs anywhere from 20fps to "infinite fps", movement is interpolated based upon frame timings. Obviously it runs smooth without limiting, it also runs smooth with vsync enabled (60fps on my monitor), but with the limiter enabled at 60fps it gets visibly choppy.
Now while v-sync is an option, v-sync isn't perfect, since it adds a slight delay to the rendering, which some people find uncomfortable to use, especially with regards to mouse movement. Of course, I could use the native windows mouse pointer, but then UI collision detection is one frame behind the current mouse location on screen, leading to clicks being registered in the wrong place. Which can be quite frustrating.
Hence, I find myself wondering if SFML's frame rate limiter is currently fit for purpose? However, I must admit, when I made the OP, I had mistakenly assumed that SFML would have a similar feature to SDL where you can tell it to sleep, upon further inspection it does not seem to. As such there isn't currently any "just works" way to do better.
So my guess would be that the only real solution is to manually time how long SFML waited for on the last frame. Then set the FPS limit each frame to purposefully undershoot slightly, and then spin hot in a while loop until the correct time is achieved.
Its hardly the end of the world, but it doesn't feel that elegant (or simple) either xD
if (frameLimiter == true){
//time: time taken to run the game code (get time before running code, get time after running code, subtract them)
//frameTarget: whatever fps is being targeted (ie, 60)
//If time is negative, the time probably overflew, ignore it and continue
if (time < 0) continue;
//Subtract the "framerate target" by the "time taken to run the game code"
float sleepTime = (1.0 / (float)frameTarget) - (time);
if (sleepTime > 0)
{
//Tell SDL to sleep until the next frame is due
SDL_Delay(sleepTime);
}
else
{
//The game took longer to run than the target, begin next frame immediately without delay
}
}
//time: time taken to run the game code (get time before running code, get time after running code, subtract them)
//frameTarget: whatever fps is being targeted (ie, 60)
//If time is negative, the time probably overflew, ignore it and continue
if (time < 0) continue;
//Subtract the "framerate target" by the "time taken to run the game code"
float sleepTime = (1.0 / (float)frameTarget) - (time);
if (sleepTime > 0)
{
//Tell SDL to sleep until the next frame is due
SDL_Delay(sleepTime);
}
else
{
//The game took longer to run than the target, begin next frame immediately without delay
}
}