C++: вычисление движущегося FPS

Я хотел бы рассчитать FPS последних 2-4 секунд игры. Как лучше всего это сделать?

Спасибо.

Редактировать: Чтобы быть более конкретным, у меня есть доступ только к таймеру с шагом в одну секунду.


person Community    schedule 14.01.2011    source источник
comment
Я думаю, что сначала вы должны предоставить некоторую информацию (код) об архитектуре вашей игры.   -  person William    schedule 14.01.2011
comment
Не так далеко, как архитектура идет. Я могу увеличивать счетчик каждый раз в основном цикле, и у меня есть доступ ко второму таймеру.   -  person    schedule 14.01.2011
comment
Что вы пытаетесь решить? Я не хочу показаться застенчивым, но из эзотерического значения вашего вопроса кажется, что вы, возможно, идете неправильным путем, чтобы решить то, что вы пытаетесь решить.   -  person David Titarenco    schedule 14.01.2011
comment
Я действительно не пытаюсь ничего решить. Просто ищу лучший способ рассчитать движущийся FPS.   -  person    schedule 14.01.2011
comment
Я не понимаю, как у тебя нет доступа к более точному таймеру. В зависимости от игры (или от того, насколько она быстрая или медленная), вы не получите ничего достаточно близкого к точному FPS, если имеете дело только с точностью до 1 секунды.   -  person Mark    schedule 14.01.2011
comment
@Mark Конечно, это может быть точным. FPS = кадров на Second. Так что я все еще могу считать количество кадров в секунду. Вот что значит ФПС.   -  person    schedule 14.01.2011


Ответы (4)


Почти пропустил совсем недавнюю публикацию. См. мой ответ об использовании экспоненциально взвешенных скользящих средних.

C++: подсчет общего количества кадров в игре

Вот пример кода.

Изначально:

avgFps = 1.0; // Initial value should be an estimate, but doesn't matter much.

Каждую секунду (при условии, что общее количество кадров за последнюю секунду равно framesThisSecond):

// Choose alpha depending on how fast or slow you want old averages to decay.
// 0.9 is usually a good choice.
avgFps = alpha * avgFps + (1.0 - alpha) * framesThisSecond;
person EmeryBerger    schedule 14.01.2011
comment
Я ищу какой-то конкретный код, я просто не уверен, что это лучший способ сделать это. - person ; 14.01.2011
comment
хм, вроде логично. если вы добавите этот код в ответ, я могу его принять. - person ; 14.01.2011
comment
Это хорошо, используя альфа для скользящей средней. Что-то в основном цикле, например:framesThisSecond++;secnow=getseconds();if(secnow!=seclast){doJaysCode;framesThisSecond=0};seclast=secnow; чтобы пересчитывать каждый раз, когда секунды выглядят так, как будто они изменились. - person david van brink; 14.01.2011

Вот решение, которое может сработать для вас. Я напишу это на псевдо/C, но вы можете адаптировать эту идею к своему игровому движку.

const int trackedTime = 3000; // 3 seconds
int frameStartTime; // in milliseconds
int queueAggregate = 0;
queue<int> frameLengths;

void onFrameStart()
{
    frameStartTime = getCurrentTime();
}

void onFrameEnd()
{
    int frameLength = getCurrentTime() - frameStartTime;

    frameLengths.enqueue(frameLength);
    queueAggregate += frameLength;

    while (queueAggregate > trackedTime)
    {
        int oldFrame = frameLengths.dequeue();
        queueAggregate -= oldFrame;
    }

    setAverageFps(frameLength.count() / 3); // 3 seconds
}
person Adam Maras    schedule 14.01.2011
comment
У меня нет точного таймера, только второй таймер. Извините, я не был более ясен в ОП. - person ; 14.01.2011

Можно ли сохранить круговой буфер времени кадра для последних 100 кадров и усреднить их? Это будет «FPS для последних 100 кадров». (Или, скорее, 99, так как вы не будете различать самое новое время и самое старое.)

Назовите какое-то точное системное время, миллисекунды или лучше.

person david van brink    schedule 14.01.2011
comment
У меня нет доступа к точному таймеру. Второй таймер - это все, что я использую. - person ; 14.01.2011
comment
Для этого вам не нужен таймер. Как раз время. Это две разные вещи. Например. многие системы могут предоставлять миллисекундные таймеры, но наносекундные. - person MSalters; 14.01.2011
comment
@MSalters Извините, я не выразился яснее, я имел в виду время = таймер, таймер = время. - person ; 14.01.2011

На самом деле вы хотите что-то вроде этого (в вашем mainLoop):

frames++;
if(time<secondsTimer()){
  time = secondsTimer();
  printf("Average FPS from the last 2 seconds: %d",(frames+lastFrames)/2);
  lastFrames = frames;
  frames = 0;
}

Если вы знаете, как работать со структурами/массивами, вам будет легко расширить этот пример, например, до 4 секунд вместо 2. Но если вам нужна более подробная помощь, вы должны действительно упомянуть, ПОЧЕМУ у вас нет доступа к точному таймер (какая архитектура, язык) - а то все как угадаешь...

person Constantin    schedule 14.01.2011
comment
на самом деле не имеет значения, почему я не использую точный таймер, но если вы хотите знать, это потому, что в настоящее время я пишу переносимый код. Я использую Linux, и библиотека, которую я использую, имеет доступ к точному времени, но, как я уже сказал, в настоящее время я хочу, чтобы мой код был переносимым. - person ; 14.01.2011