这一节我们学习如何制作一个高分辨率的定时器。这个可以用来确保我们的物体在1秒内的距离是确定的,不管我们的游戏每秒有60帧还是6帧(因为我们之前世界矩阵的变换是基于每一帧的)
Global Declarations
double countsPerSecond = 0.0;
__int64 CounterStart = 0;
int frameCount = 0;
int fps = 0;
__int64 frameTimeOld = 0;
double frameTime;
New and Modified Functions
void UpdateScene(double time);
void RenderText(std::wstring text, int inInt);
void StartTimer();
double GetTime();
double GetFrameTime();
我们创建了一些新的函数以及修改了一些之前的函数参数
updatescene我们把每一帧渲染的时间作为参数。
rendertext我们把FPS作为参数,让它显示(其实它已经是全局变量了,但是这样更清晰)
下面三个函数,第一个用来启动定时器。第二个用来测量我们我们距离start开始的时间,每一帧对framecount+1;每秒把值传入fps,然后清空framecount。第三个用来得到每帧的持续时间。
Timer Functions
我们这里调用两个win32函数
QueryPerformanceFrequency(),返回一个64位整数,代表每秒的计数。(频率)
我们使用QueryPerformanceCounter,得到当前时间的计数,也是一个64位整数。
所以starttimer函数把频率变量存储在countspersecond里,把当前时间存储在counterstart里
gettime函数得到当前时间,存储在current time里。我们从current里减去conterstart,得到从开始到现在的时间。然后我们除每秒钟的计数值,得到从开始到现在的秒数。
GetFrameTime函数基本上做了前两个函数的事情,除了找从开始到现在的时间,我们得到上一次调用这个函数的时间,然后返回每帧需要的秒数。这个可以用来保证我们的相机和动画平稳移动。
void StartTimer()
{
LARGE_INTEGER frequencyCount;
QueryPerformanceFrequency(&frequencyCount);
countsPerSecond = double(frequencyCount.QuadPart);
QueryPerformanceCounter(&frequencyCount);
CounterStart = frequencyCount.QuadPart;
}
double GetTime()
{
LARGE_INTEGER currentTime;
QueryPerformanceCounter(¤tTime);
return double(currentTime.QuadPart-CounterStart)/countsPerSecond;
}
double GetFrameTime()
{
LARGE_INTEGER currentTime;
__int64 tickCount;
QueryPerformanceCounter(¤tTime);
tickCount = currentTime.QuadPart-frameTimeOld;
frameTimeOld = currentTime.QuadPart;
if(tickCount < 0.0f)
tickCount = 0.0f;
return float(tickCount)/countsPerSecond;
}
The UpdateScene() Functions New Parameter
之前我们对于物体每帧都旋转一个固定值,如果30帧,物体就会转很慢,如果每秒300帧,物体就转很快。
现在我们把固定值乘每帧渲染的时间,如果时间长,固定值就大,如果时间段固定值就小。这样每秒转的角度都是一样的。
rot += 1.0f * time;
Add the New Param. To printString
printString << text <<inInt;
这样打印出来就是FPS:50。
Call the RenderText() Function, Passing in the FPS
RenderText(L"FPS: ", fps);
frameCount++;
if(GetTime() > 1.0f)
{
fps = frameCount;
frameCount = 0;
StartTimer();
}
frameTime = GetFrameTime();
UpdateScene(frameTime);
这里就是我们消息循环的部分,当超过一秒时,重新计数。
讲到这里,这节内容终于讲完拉~
本节内容的代码部分可以在我的github里面找到!
游戏开发路途遥远,但我相信只要坚持,总能到达彼岸!
如果我的文章对于你学习DirectX11有点帮助,欢迎评论给出建议,让我们一起学习进步!
———————— 小明 2018.12.9 16.07