SDL - проблемы с FPS с LoopTimer в С++

Мы делаем игровой движок для нашего класса C++, и мы в основном закончили со всем, за исключением небольших проблем с FPS. Он всегда работает примерно на 10-20% медленнее, чем мы его установили, и нам интересно, связано ли это с ошибкой/дерьмовым кодом или это просто так? Он ограничивается 350, если мы установим его на 500+, но это в основном из-за того, что компьютер не может обрабатывать больше. Если мы установим его на 50, мы получим около 40-44.

Вот несколько фрагментов из класса LoopTimer, обрабатывающего таймер.

Заголовок:

class LoopTimer {
public:
    LoopTimer(const int fps = 50);
    ~LoopTimer();

    void Update();
    void SleepUntilNextFrame();

    float GetFPS() const;
    float GetDeltaFrameTime() const { return _deltaFrameTime; }

    void SetWantedFPS(const int wantedFPS);
    void SetAccumulatorInterval(const int accumulatorInterval);

private:
    int _wantedFPS;
    int _oldFrameTime;
    int _newFrameTime;
    int _deltaFrameTime;
    int _frames;
    int _accumulator;
    int _accumulatorInterval;
    float _averageFPS;
};

CPP-файл

LoopTimer::LoopTimer(const int fps)
{
    _wantedFPS = fps;
    _oldFrameTime = 0;
    _newFrameTime = 0;
    _deltaFrameTime = 0;
    _frames = 0;
    _accumulator = 0;
    _accumulatorInterval = 1000;
    _averageFPS = 0.0;
}
void LoopTimer::Update()
{
    _oldFrameTime = _newFrameTime;
    _newFrameTime = SDL_GetTicks();
    _deltaFrameTime = _newFrameTime - _oldFrameTime;

    _frames++;
    _accumulator += _deltaFrameTime;

    if(_accumulatorInterval < _accumulator)
    {
        _averageFPS = static_cast<float>(_frames / (_accumulator / 1000.f));
        //cout << "FPS: " << fixed << setprecision(1) << _averageFPS << endl;
        _frames = 0;
        _accumulator = 0;
    }
}


void LoopTimer::SleepUntilNextFrame()
{
    int timeThisFrame = SDL_GetTicks() - _newFrameTime;
    if(timeThisFrame < (1000 / _wantedFPS))
    {
        // Sleep the remaining frame time.
        SDL_Delay((1000 / _wantedFPS) - timeThisFrame);
    }
}

Обновление в основном вызывается в нашем GameManager в методе run:

int GameManager::Run()
{
while(QUIT != _gameStatus)
    {
        SDL_Event ev;

        while(SDL_PollEvent(&ev))
    {
            _HandleEvent(&ev);
    }

    _Update();
    _Draw();

    _timer.SleepUntilNextFrame();
   }    
    return 0;
}

Я могу дать еще немного кода, если это необходимо, или я был бы рад дать код всем, кому он может понадобиться. Это довольно много, включая функции sdl_net и все такое, поэтому нет смысла сбрасывать все это сюда.

В любом случае, я надеюсь, что у кого-то есть умный совет относительно частоты кадров, либо о том, как ее улучшить, либо о другой функции циклического таймера, либо просто о том, что небольшая потеря в частоте кадров — это нормально :)


person Anders Vedal Pettersen    schedule 14.04.2012    source источник


Ответы (1)


Я думаю, что в вашей функции есть ошибка

int timeThisFrame = /* do you mean */ _deltaFrameTime;  //SDL_GetTicks() - _newFrameTime;
person eale    schedule 19.04.2012
comment
Это на самом деле привело к тому, что частота кадров выше, чем желаемая частота кадров: P на 200 она выросла до 270. Возможно, это ошибка с математикой, стоящей за средним значением частоты кадров, но я посмотрю повнимательнее. Спасибо хоть :) - person Anders Vedal Pettersen; 24.04.2012