Jump to content
  • Advertisement
MarcusAseth

60 FPS game loop using std::chrono

This topic is 421 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone, out of curiosity yesterday I was trying out chrono header with the goal of creating a 60fps loop, the code below is what I have so far and I wanted your opinion about it, if it is the proper way to do it, how it is usually done or how I could improve on it .

Thanks :)

#include <iostream>
#include <chrono>
#include <cstdint>
using namespace std;
using namespace chrono;

using frame = duration<int32_t, ratio<1, 60>>;
using ms = duration<float, milli>;

int main()
{
	time_point<steady_clock> fpsTimer(steady_clock::now());
	frame FPS{};

	while (true)
	{
		FPS = duration_cast<frame>(steady_clock::now() - fpsTimer);
		if (FPS.count() >= 1)
		{
			fpsTimer = steady_clock::now();
			cout << "LastFrame: " << duration_cast<ms>(FPS).count() << "ms  |  FPS: " << FPS.count() * 60 << endl;
		}
	}
	return 0;
}

output:

LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60
LastFrame: 16.6667ms  |  FPS: 60

Edited by MarcusAseth

Share this post


Link to post
Share on other sites
Advertisement

The 60 frames per second really only applies to game consoles where the TV monitor is running at 60 frames per second because that's what the old television standards used.

If you're on a monitor running at 75 frames per second, 60 is probably not your ideal target.

There are many good articles about the typical game loop, here are two often recommended articles:

Clicky - DeWiTTERS

Clicky - Gaffer

Share this post


Link to post
Share on other sites
On 7/16/2017 at 10:52 PM, MarcusAseth said:

I'll go check them out, thanks frob :)

I would strongly recommend you do not lock render frames in your time step, but you render your input and logic at a certain amount of ticks per second, and render graphics as fast as possible with the remaining time until the next frame is due. You will have to use interpolation to smooth out movement however. This will make sure you're getting smooth graphics at any FPS.

I'm using a similar loop like DeWitters with interpolation. Works like a charm. Also, stay away from variable rates for logic and input, it can do some wonky things with collision among other things. I always prefer Fixed Time Steps with Variable Render Rates using Interpolation.

Share this post


Link to post
Share on other sites

derived from, fix your timestep, I am using this:

mPlaying = true;

int lag = 0;
std::chrono::time_point<std::chrono::steady_clock> endTime = std::chrono::steady_clock::now();

long longestTime = 0;
long frameCount = 0;
long tickCount = 0;
long fpsElapsedTime = 0;

while (mPlaying) {

	std::chrono::time_point<std::chrono::steady_clock> startTime = std::chrono::steady_clock::now();

	std::chrono::milliseconds elapsedTime(std::chrono::duration_cast<std::chrono::milliseconds>(startTime - endTime));
	endTime = startTime;

	lag += static_cast<int>(elapsedTime.count());

	if (elapsedTime.count() == 0) { //the sim loop will not be run if lag was not increased prior ( previous frame normally )
		Sleep(5); 
	}

	const int fps = 60;
	const int lengthOfFrame = 1000 / fps;

	MSG msg;
	while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	//game-sim loop, is independent of rendering
	std::chrono::time_point<std::chrono::steady_clock> oldTime = std::chrono::steady_clock::now();
	while (lag >= lengthOfFrame) {
		//update the player and ship
		if (!getInput()) break;

		game.step();					

		//finish tick
		lag -= lengthOfFrame;
		tickCount++;	//keep track of how many ticks weve done this second
	}

	//render the frame
	Graphics::get().getRoot()->renderOneFrame();
	frameCount++;	//keep trrack of how many frames weve done this second

	//handle per-second stats
	fpsElapsedTime += static_cast<long>(elapsedTime.count());
	if (fpsElapsedTime >= 1000) {

		std::stringstream sstr;
		sstr << frameCount << ", "
					 << tickCount;

		mCefGui->writeJavascript("setStatus", sstr.str().c_str(), url);
		fpsElapsedTime = 0;
		frameCount = 0;
		tickCount = 0;
	}
}
	

 

Edited by h8CplusplusGuru

Share this post


Link to post
Share on other sites

Thanks for the feedback guys, I am putting this on hold because I'm swamped in math (trying to watch ALL khan academy videos in order, 600 videos in), but when the times come I'm definetly putting my full attention into this :P

Share this post


Link to post
Share on other sites
10 hours ago, MarcusAseth said:

Thanks for the feedback guys, I am putting this on hold because I'm swamped in math (trying to watch ALL khan academy videos in order, 600 videos in), but when the times come I'm definetly putting my full attention into this :P

If you need help later on, just send me a PM.

@h8CplusplusGuru not sure if your loop is just an example to run and show, but you should never 'sleep' when waiting, it's not a good practice. You cannot guarantee when sleep will end, only that sleep will start and stay as such for the minimum time you set. Don't use it to regulate frames.

Share this post


Link to post
Share on other sites
1 minute ago, h8CplusplusGuru said:

It really only matters when debugging the loop, such that elapsedTime may == 0. In actual app that is unlikely, and the sleep is not ran. It actually makes sense to have sleep(5) if you were to troll the code more effectively. 

No problem. I just need to state this because new programmers are using sleep to regulate Frames, and it's a horrible practice.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!