SFML community forums

Help => System => Topic started by: BaneTrapper on December 25, 2013, 03:04:47 pm

Title: Using sf::Clock and std::this_thread::sleep_for to achieve X fps bad results
Post by: BaneTrapper on December 25, 2013, 03:04:47 pm
Hello.
I am trying to achieve a system that will handle events at 100 fps while game will run on 1-60 fps.
The issues is that the outer loop is not accurate and i will post my math, pretty sure it sould be working any tips/help?

The logic i am using goes something like this
if DesiredLoopLastTime - LastLoopTime > 0
then pause for DesiredLoopLastTime - LastLoopTime
This produces 67 fps instead of 100  :(

Code: [Select]
//Time.cpp
void Time::LoopTime()
{
//Pause here to make last loop last 10ms or desired amount
int tmpTime = threadClock.getElapsedTime().asMilliseconds();
if(10 - tmpTime > 0)
std::this_thread::sleep_for(std::chrono::milliseconds(10 - tmpTime));

dt = threadClock.restart().asMilliseconds();

if(isPaused)//Dont loop logic if paused
return;

//Thread
threadCounter++;
//Logic
logicAccumulated += dt;
if(logicAccumulated > logicRequired * 2)
logicAccumulated = logicRequired*2;
//Fps
fpsAccumulated += dt;
if(fpsAccumulated > fpsRequired)
{
fpsAccumulated -= fpsRequired;
//Update fps data
txtThread.setString("FPST:"+std::to_string(threadCounter));
threadCounter = 0;
txtLogic.setString("FPSL:"+std::to_string(logicCounter));
logicCounter = 0;
}
}

//Main.cpp
//The main while loop

while(objState.GetAppState() != en::AppState::APExit)
{
objTime.LoopTime();//Once per loop
if(objState.GetAppState() != en::AppState::APPause)
{
//objEvent.HandleEvents(objWin.Win, objState, objTime, en::EventHandleTypes::EHAll);//Once per loop //Of this type

while(objTime.logicAccumulated > objTime.logicRequired)//If logic update
{
objTime.logicAccumulated -= objTime.logicRequired;
objTime.LoopLogicTime();

objEvent.HandleEvents(objWin.Win, objState, objTime, en::EventHandleTypes::EHAll);//Once per loop //Of this type
objWin.Win.clear(sf::Color(0,0,0,255));

if(objState.GetGameState() == en::GameState::GSMainMenu)
{
objMenu.LoopMenu(objEvent, objState);
objMenu.DrawMenu(objWin.Win);
}
else if(objState.GetGameState() == en::GameState::GSGame)
{
objPlayer.LoopPlayer(objEntity, objEvent, objTime.logicRequired);
objMap.LoopMap(objEvent, objState);

objMap.DrawMap(objWin.Win);
objEntity.DrawEntity(objWin.Win);
objInventory.DrawInventory(objWin.Win);
}
else if(objState.GetGameState() == en::GameState::GSEditor)
{
objMap.LoopEditor(objEvent, objState);

objMap.DrawEditor(objWin.Win);
}
objTime.DrawTime(objWin.Win);
objEvent.ClearDataPerLoop();
}
}
else//App state == pause
{
objEvent.HandleEvents(objWin.Win, objState, objTime, en::EventHandleTypes::EHApp);//Once per loop //Of this type
}
objWin.Win.display();//Once per loop
}
This is Time and main while loop.
The inner FPS other called Logic fps is 60-61 but the Thread fps is not stable at all and varies from 60-100 and after 10-15 sec or app running it stops at ~67-70 and does not change.


EDIT::
Minimal example coming soon.
Title: Re: Using sf::Clock and std::this_thread::sleep_for to achieve X fps bad results
Post by: Jesper Juhl on February 03, 2014, 08:29:05 pm
First of all, the time per frame *will* vary depending on lots of things like; the work you do per frame, the resolution of your operating systems timers/scheduling frequency, other processes running on the machine, power-saving features of the hardware (like frequency scaling etc) and many other things. Never depend on timers or fps being stable or predictable.

Second; you may *want* 100fps, but is your hardware able to achieve that? What about other peoples machines? You simply can't make that kind of assumptions.

Third; read this: http://gafferongames.com/game-physics/fix-your-timestep/ (http://gafferongames.com/game-physics/fix-your-timestep/)

EDIT: also take a look at the documentation for setVerticalSyncEnabled() and setFramerateLimit() .