user3023723
user3023723

Reputation: 7

C++ win32 printing to console in fixed timesteps

I am trying to create a function that will allow me to enter the desired frames per second and the maximum frame count and then have the function "cout" to the console on the fixed time steps. I am using Sleep() to avoid busy waiting as well. I seem to make the program sleep longer than it needs to because it keeps stalling on the sleep command i think. Can you help me with this? i am having some trouble understanding time, especially on windows.

Ultimately i will probably use this timing method to time and animate a simple game , maybe like pong, or even a simple program with objects that can accelerate. I think i already understand GDI and wasapi enough to play sound and show color on the screen, so now i need to understand timing. I have looked for a long time before asking this question on the internet and i am sure that i am missing something, but i can't quite put my finger on it :( here is the code :

#include <windows.h>
#include <iostream>

// in this program i am trying to make a simple function that prints frame:  and the number frame  in between fixed time intervals
// i am trying to make it so that it doesn't do busy waiting

using namespace std;


void frame(LARGE_INTEGER& T, LARGE_INTEGER& T3, LARGE_INTEGER& DELT,LARGE_INTEGER& DESI, double& framepersec,unsigned long long& count,unsigned long long& maxcount,bool& on, LARGE_INTEGER& mili)
{
    QueryPerformanceCounter(&T3); // seccond measurement

    DELT.QuadPart = &T3.QuadPart - &T.QuadPart; // getting the ticks between the time measurements

    if(DELT.QuadPart >= DESI.QuadPart) {count++; cout << "frame: " << count << " !" << endl; T.QuadPart = T3.QuadPart; } // adding to the count by just one frame (this may cause problems if more than one passes)

     if(count > maxcount) {on = false;} // turning off the loop

    else {DESI.QuadPart = T.QuadPart + DESI.QuadPart;//(long long)framepersec; // setting the stop tick
        unsigned long long sleep = (( DESI.QuadPart - DELT.QuadPart) / mili.QuadPart);
        cout << sleep << endl;
        Sleep(sleep);} // sleeping to avoid busy waiting
}


int main()
{

    LARGE_INTEGER T1, T2, Freq, Delta, desired, mil;
    bool loopon = true; // keeps the loop flowing until max frames has been reached

    QueryPerformanceFrequency(&Freq); // getting num of updates per second
    mil.QuadPart = Freq.QuadPart / 1000; // getting the number clock updates that occur in  a millisecond
    double framespersec; // the number of clock updates that occur per target frame
    unsigned long long framecount,maxcount; //to stop the program after a certain amount of frames
    framecount = 0;


    cout << "Hello world! enter the amount of frames per second : " << endl;
    cin >> framespersec;
    cout << "you entered: " << framespersec << " ! how many max frames?" << endl;
    cin >> maxcount;
    cout << "you entered: " << maxcount << " ! now doing the frames !!!" << endl;
    desired.QuadPart = (Freq.QuadPart / framespersec);

    while(loopon == true) {
        frame(T1, T2, Delta, desired, framespersec, framecount, maxcount,loopon, mil);
    }


    cout << "all frames are done!" << endl;
    return 0;
}

Upvotes: 0

Views: 480

Answers (2)

awr
awr

Reputation: 550

The time that you sleep is limited by the frequency of the system clock. The frequency defaults to 64 Hz, so you'll end up seeing sleeps in increments of 16ms. Any sleep that's less than 16ms will be at least 16ms long - it could be longer depending on CPU load. Likewise, a sleep of 20ms will likely be rounded up to 32ms.

You can change this period by calling timeBeginPeriod(...) and timeEndPeriod(...), which can increase sleep accuracy to 1ms. If you have a look at multimedia apps like VLC Player, you'll see that they use these functions to get reliable frame timing. Note that this changes the system wide scheduling rate, so it will affect battery life on laptops.

More info: http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298%28v=vs.85%29.aspx

Upvotes: 2

Ben Voigt
Ben Voigt

Reputation: 283614

Waitable timers are more accurate than Sleep, and also integrate with a GUI message loop better (replace GetMessage with MsgWaitForMultipleObjects). I've used them successfully for graphics timing before.

They won't get you high precision for e.g. controlling serial or network output at sub-millisecond timing, but UI updates are limited by VSYNC anyway.

Upvotes: 0

Related Questions