I’ve pondered, for a while, on the merits of me writing out every lesson I learn on my journey to become a game programmer, and I think that the HOWTO format is not going to be sustainable. So, from now on I’ll be jotting down some notes, and some key points, but I’ll be dispensing with full code listings and blow-by-blow coverage of what’s going on.
So, on to timers and clocks in DirectX.
Timing is everything
Clearly, animation, physics and many other calculations need to be based on some measure of time. Ideally we’d like to know how long since the last frame. We’d probably also like to know how long we’ve been running for, and we’d also like to know the elapsed time versus “game” time (wall-clock versus time actually spent playing).
So, the first order of business is finding out the current time. Windows has the Performance Timer, and it measures in counts. We can find out how many counts there are per second and thus convert all our timings to seconds. The following functions are of use to us:
QueryPerformanceCounter( LARGE_INTEGER* currentTime ); // Writes the current time in counts into the address pointed to by currentTime QueryPerformanceFrequency( LARGE_INTEGER* countsPerSec ); // Get how many seconds per count there are
So, we can quite easily get the current time in seconds (not entirely sure since when, but hey it doesn’t really matter). If we store this value, and then get a new value some time from now we can easily find out a measure of the time between this. So our class will have a private member which stores the last time value we queried, and also the last delta we worked out. We’ll then have a tick member function to refresh this. On might like to call this every frame or something.
So, how about total time? We’ll store the time when we start the timer, and then we can get a delta between the very first time and now. To allow us to pause the clock, we’ll keep track of the time whenever we pause it, and whenever we unpause the clock we’ll increment a counter of the time spent paused with the delta between pausing and unpausing – then, if we want to ignore time spent paused we simply subtract that from the overall elapsed time since we started. We’ll also store the current time every time we tick. I can’t see much point from the way the clock is implemented in the Luna book, but I’m going to use the current time member in all the other methods, rather than re-querying the current time. My reason for this is so that we truly quantise time, rather than have slight differences part way through the frame. In all likelihood the timer is not accurate enough for this to be an issue, but we’ll be perfectionist.
It’d be nice to be able to reset our timer as well.
Oddly enough, DirectX has built in text functionality, so why XNA uses sprite-sheet based text drawing is a mystery to me. I guess maybe the xbox does not have a comparable font engine to windows, and as such all xbox code needs to use sprite-based fonts. Makes sense I guess.
Anyhow, to do text you need to describe the font that you want, and then get DirectX to create it and return a pointer to it for you. Then you simply draw the text. I’m going to stick the code in my initialiseDirect3d() member function. The code you need to describe the font is the following:
D3DX10_FONT_DESC font; font.Height = 24; font.Width = 0; font.Weight = 0; font.MipLevels = 1; font.Italic = false; font.CharSet = DEFAULT_CHARSET; font.OutputPrecision = OUT_DEFAULT_PRECIS; font.Quality = DEFAULT_QUALITY; font.PitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; wcscpy(font.FaceName, L"Times New Roman"); D3DX10CreateFontIndirect(this->device, &font, &( this->defaultFont ) );
Finally I’ll draw the text in my draw method, outputting the frame rate and last frame time, using the following method:
INT ID3DX10Font::DrawText( LPD3DX10SPRITE pSprite, // Can be null LPCSTR pString, INT Count, // -1 seems to output the whole string LPRECT pRect, // can just use a zero width/height to position text if UINT Format, // you use DT_NOCLIP here D3DXCOLOR Color );