1

just wondering how I would go about adding ints to an array in the following way;

I am getting average framerate for my game, but from what I understand if I create an int array of [10], I have no native way of just adding a number to the start of the array.

I want to do this.

myInt[0] = 60
myInt[1] = 59
myInt[2] = 61

I want to add, say, 30, to myInt[0], and have it move the current myInt[0] to [1] and [1] to [2], so it just moves everything along one and drops the last integer from the array.

What I've tried to do so far just changes [0], making my average calculations useless. Also, I'm using SDL_GetTicks() to snag the current elapsed time.

Is there a better way to do average framerate?

Sam
  • 7,252
  • 16
  • 46
  • 65
  • You don't need an array. Just keep a sum. Or am I missing something? – Mysticial Jan 13 '12 at 04:50
  • 1
    you can use std::queue for that :D – codekiddy Jan 13 '12 at 04:52
  • For a running average like this, I'd suggest using a deque. – Yuushi Jan 13 '12 at 04:53
  • @Mystical: if you maintain only a sum, wouldn't that result in an average over the lifetime of the program? Maybe user1146958 wants the average over the last 10 ticks of program execution, showing only "recent" framerate averages. – veefu Jan 13 '12 at 04:57
  • @veefu It wasn't clear to me from the start. But after all these comments, yes, a sliding window of averages does seem to be what the OP wants. – Mysticial Jan 13 '12 at 04:59
  • See [Boost.CircularBuffer](http://www.boost.org/libs/circular_buffer/). – ildjarn Jan 13 '12 at 05:13
  • Is that what it's called? A sliding window of averages? That's exactly what I'm looking for. – ThomasuDesu Jan 13 '12 at 05:29
  • In that case, see [Boost.Accumulators](http://www.boost.org/libs/accumulators/). Don't reinvent the wheel. – ildjarn Jan 13 '12 at 16:17

3 Answers3

2

sounds like you want a circular queue. I would investigate the operator "%" with a frame counter. Your frame counter always goes up, you update myInt[frame_counter % MY_INT_LENGTH], then map reduce myInt and divide by MY_INT_LENGTH.

I would suggest storing the last 8 or 16 frame rates instead of 10. This makes the mod operator a bit mask.

EDIT

If you want an average frame rate what you should really do is check delta_frames / delta_time

In your render thread or an observer increment a counter each frame render. then ask how many frames and divide by the time difference. You can poll the average frame rate asynchronously and reset the frame counter on poll.

EnabrenTane
  • 7,428
  • 2
  • 26
  • 44
  • I dont think there is need of circular queue... A Simple queue will be enough as mentioned by @Pubby... – Amit Jan 13 '12 at 05:01
  • Implementing a full Queue as above requires far more memory operations, than using mod on a static array. – EnabrenTane Jan 13 '12 at 05:04
  • 1
    true.... but that is the implementation part, we cant say that you need circular queue.. the Behavior is diff for both cases.... +1 for a Good answer though!! – Amit Jan 13 '12 at 07:05
1

std::vector is what you should be using instead of arrays, although std::queue in this case.

Quick/messy code showing how that would work:

int sum = 0; // should be wrapped in a class or something
const int max_size = 10;

void add(std::queue<int>& q, int fps) {
  q.push(fps);
  if(q.size() > max_size) {
    sum -= q.front();
    q.pop();
  }
  sum += fps;
}

int avg(std::queue<int>& q) {
  return sum / q.size();
}

//...

std::queue<int> myQ;
add(myQ, 60);
add(myQ, 61);
add(myQ, 50);
std::cout << avg(myQ);

You should be able to see the method as you seem to understand it in your original code.

Pubby
  • 51,882
  • 13
  • 139
  • 180
  • +1 for good and quick answer, this is what I was typing suddenly SO said 1 new answer posted. – Amit Jan 13 '12 at 05:02
0

Is there a better way to do average framerate?

Why yes....

Here is some code that I have used before to keep track of "frame rate" for a video rendering application. It was written for a Windows app. If you aren't using Windows, then replace all the "DWORD" types below with "unsigned int". And replace the GetTickCount call with SDL_getticks() function. It's pretty straightforward. Call OnFrame every time you render a new frame. Call GetFrameRate whenever you want to know it.

class CFrameRateMonitor
{
private:
    static const DWORD DEFAULT_INTERVAL = 2000;
    bool m_fFirstFrame;
    DWORD m_dwInterval;  // how often we recompute the average
    DWORD m_dwFrames;
    DWORD m_dwStartTime;
    DWORD m_dwComputedRate;
public:
    CFrameRateMonitor();

    void Reset();
    void OnFrame();
    DWORD GetFrameRate();
    void SetInterval(DWORD dwInterval);
};



CFrameRateMonitor::CFrameRateMonitor()
{
    Reset();
    m_dwInterval = DEFAULT_INTERVAL;
}

void CFrameRateMonitor::SetInterval(DWORD dwInterval)
{
    m_dwInterval = dwInterval;
}

void CFrameRateMonitor::Reset()
{
    m_dwFrames = 0;
    m_dwStartTime = 0;
    m_dwComputedRate = 0;
    m_fFirstFrame = true;
}

DWORD CFrameRateMonitor::GetFrameRate()
{
    return m_dwComputedRate;
}

void CFrameRateMonitor::OnFrame()
{
    DWORD dwCurrentTime = GetTickCount();
    DWORD dwActualInterval = dwCurrentTime - m_dwStartTime;

    if (m_fFirstFrame)
    {
        m_dwStartTime = dwCurrentTime;
        m_fFirstFrame = false;
    }
    else
    {
        m_dwFrames++;
        if (dwActualInterval >= m_dwInterval)
        {
            // enough time has passed to compute a new interval
            // + 500 to "round up"
            m_dwComputedRate = (m_dwFrames * 1000 + 500) / dwActualInterval; 
            // reset counting
            m_dwStartTime = dwCurrentTime;
            m_dwFrames = 0;
        }
    }
}
selbie
  • 100,020
  • 15
  • 103
  • 173