在上篇教程代码的基础上,我们增加一个TimerClass类,这个类的功能很简单,就是可以计算相邻2帧的时间差。利用这个时间差值,可以实现平滑的动画,使得动画不会因为不同机器fps不同,从而动画效果变快或者变慢。
我们主要是利用QueryPerformanceCounter函数来查询定时器的计数值。
如果硬件里有定时器,它会启动这个定时器,之后会不断获取定时器的值,这样的定时器精度,就跟硬件时钟的晶振一样精确的。
TimerClass.h代码如下:
#pragma once #include <windows.h>
//主要用来计算相邻两帧之间的时间 //可以用来实现平滑的与fps无关的动画。 class TimerClass { public: TimerClass(void); TimerClass(const TimerClass&); ~TimerClass(void); bool Initialize(); void Frame();
float GetTime();
private: INT64 m_frequency; float m_ticksPerMs; INT64 m_startTime; float m_frameTime;
};
TimerClass.cpp代码如下:
#include "TimerClass.h"
TimerClass::TimerClass(void) { }
TimerClass::TimerClass(const TimerClass& other) { }
TimerClass::~TimerClass(void) { }
bool TimerClass::Initialize() { // 检测系统是否支持高精度计时器. QueryPerformanceFrequency((LARGE_INTEGER*)&m_frequency); if(m_frequency == 0) { return false; }
// 得到每毫秒多少个计数器. m_ticksPerMs = (float)(m_frequency / 1000);
QueryPerformanceCounter((LARGE_INTEGER*)&m_startTime);
return true; }
//每个渲染帧都会被调用,从而计算出每帧之间的时间 void TimerClass::Frame() { INT64 currentTime; float timeDifference;
QueryPerformanceCounter((LARGE_INTEGER*)& currentTime);
timeDifference = (float)(currentTime - m_startTime);
m_frameTime = timeDifference / m_ticksPerMs;
m_startTime = currentTime;
return; }
float TimerClass::GetTime() { return m_frameTime; }
我们在SystemClass.h中增加一些代码,包含TimerClass.h
…
#include "GraphicsClass.h" #include "TimerClass.h"
const float PI = 3.14159265358979323f;
class SystemClass { …
GraphicsClass* m_Graphics;
//计时器类 TimerClass* m_Timer; };
SystemClass.cpp代码如下,我只贴出了修改了代码的函数。
#include "SystemClass.h"
SystemClass::SystemClass(void) { m_Input = 0; m_Graphics = 0;
m_Timer = 0;
}
//调用窗口初始化函数和其它一些类的初始化函数 bool SystemClass::Initialize() { … // 初始化图形对象 result = m_Graphics->Initialize(screenWidth, screenHeight, m_hwnd); if(!result) { return false; } // 创建计时器对象. m_Timer = new TimerClass; if(!m_Timer) { return false; }// 初始化计时器对象 result = m_Timer->Initialize(); if(!result) { MessageBox(m_hwnd, L"Could not initialize the Timer object.", L"Error", MB_OK); return false; }
return true; }
bool SystemClass::Frame() { …m_Timer->Frame();
根据时间来设定摄像机旋转的角度,基本上能保证旋转不会因为fps不同而不同
//动画,旋转摄像机 m_Graphics->m_Camera->roll(m_Timer->GetTime()/1000);
// 执行帧渲染函数. result = m_Graphics->Frame(); if(!result) { return false; } return true; }
程序执行后,将会发现一个旋转的颜色立方体,你也可以用Q,W,E,A,S,D,Z,X,C控制摄像机,改变观察方向。
程序的截图和上篇教程中的图是一样的。
完整的代码请参考:
工程文件myTutorialD3D11_8
代码下载: