Как добиться нужного fps?

Из расчета 1000мс/30фпс = 33.3333 мс мы получаем, что должны выполнять какие-либо действийя не менее чем через 33.3мс для получения 30fps. Но у меня каждый запуск выходит 21фпс. Вот код:
bool Game::run(void)
{
	startTime = GetTickCount(); //получаем время прошедшее с запуска программы
	frameCount = 0; //подсчет фреймов
	lastTime = 0;

	char key = ' ';

	while(key != 'q') //пока не нажали на выход
	{
		while(!getInput(&key)) 
		{
			timerUpdate(); //обновляем 
		}

		cout << "You pressed: " << key << endl;
	}
	cout << frameCount / ((GetTickCount() - startTime) / 1000) << "fps" << endl; //высчитываем фпс по формуле: [Кол-во сделанных фреймов / на прошедшее время после старта в сек]

	return true;
}

bool Game::getInput(char *c)
{
	if( kbhit() ) //если клавиша нажата
	{
		*c = getch(); //то считать
		return true;
	}
	//иначе
	return false;
}

void Game::timerUpdate(void)
{
	double currentTime = GetTickCount() - lastTime; //получаем текущее время выполнения

	if(currentTime < GAME_SPEED) //если оно меньше 33,33мс(нужной частоты), то ждем еще, чтобы обновить фрейм 
		return;
	else
		frameCount++; //иначе обновляем фрейм, т.к. время пришло

	lastTime = GetTickCount(); //получаем конечное время
}
  • Вопрос задан
  • 3001 просмотр
Решения вопроса 1
AxisPod
@AxisPod
Ну во первых для этого существуют high-resolution timers. И никогда для этого не используйте GetTickCount и подобные. В винде для этого надо использовать multimedia timers. В принципе можно использовать boost::asio для этого. Здесь требуется событийная система.

Дальше, что сильно пугает, так это опрос клавиатуры, вы не сможете таким образом нажать 2 клавиши одновременно. Так никогда не стоит делать. В винде для этого есть RawInput. Как в никсах уже не подскажу.

А вообще возьмите готовый движок, не парьте мозг.

P.S. А вообще почитайте как организуются игровые циклы. В основном цикле заводится некий таймер, но он не предназначен для контроля fps (тут как я сказал выше нужен high-resolition timer и очень желательно событийный), он предназначен для расчета состояния игрового мира, чтобы скорость игры не зависила от кол-ва fps. На деле FPS обычно контролируется средствами системы (а в частности видеокарты) и называется это "ожидания луча" (в древности), ныне называется просто синхронизация кадра/видео и что-нить еще. При этом она может быть кратной вертикальной частоте монитора, если монитор имеет частоту 60, то вы можете получить частоту кадров 30. В этом вам спокойно помогут готовые игровые движки.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
bogolt
@bogolt
Если хотите понизить фпс ( я так понял по вопросу что хотите вы именно этого ), то после вычислений времени текущего цикла, добавляйте sleep() на недостающее количество миллисекунд.
Например вам нужно чтобы 1 цикл выполнялся за 30 мс, а он выполнлился за 20, значит нужно поспать еще 10 до выхода из цикла.
Ответ написан
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
А зачем ждать? Это вы так бережете CPU?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы