计时和动画
要正确实现动画效果,我们就必须记录时间,尤其是要精确测量动画帧之间的时间间隔。当帧速率高时,帧之间的时间间隔就会很短;所以,我们需要一个高精确度计时器。
1. 性能计时器
我们使用性能计时器(或性能计数器)来实现精确的时间测量。为了使用用于查询性能计时器的Win32函数,我们必须在代码中添加包含语句“#include
__int64 currTime;
QueryPerformanceCounter((LARGE_INTEGER*)&currTime);
注意,该函数通过它的参数返回当前时间值,该参数是一个64位整数。我们使用QueryPerformanceFrequency函数来获取性能计时器的频率(每秒的计数次数):
__int64 countsPerSec;
QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec);
而每次计数的时间长度等于频率的倒数(这个值很小,它只是百分之几秒或者千分之几秒):
mSecondsPerCount = 1.0 / (double)countsPerSec;
这样,要把一个时间读数valueInCounts转换为秒,我们只需要将它乘以转换因子 mSecondsPerCount:
valueInSecs = valueInCounts * mSecondsPerCount;
由QueryPerformanceCounter函数返回的值本身不是非常有用。我们使用QueryPerformanceCounter函数的主要目的是为了获取两次调用之间的时间差——在执行一段代码之前记下当前时间,在该段代码结束之后再获取一次当前时间,然后计算两者之间的差值。也就是,我们总是查看两个时间戳之间的相对差,而不是由性能计数器返回的实际值。下面的代码更好地说明了这一概念:
__int64 A = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&A);
/* Do work */
__int64 B = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&B);
这样我们就可以知道执行这段代码所要花费的计数时间为(B−A),或者以秒表示的时间为(B−A)*mSecondsPerCount。
注意:MSDN指出当使用QueryPerformanceCounter函数时,有以下注意事项:“在多处理器计算机中,任何一个处理器单独调用该函数都不会出现问题。但是,由于基础输入/输出系统(BIOS)或硬件抽象层(HAL)存在技术瓶颈,所以你在不同的处理器上调用该函数会得到不同的结果”。你可以使用SetThreadAffinityMask函数让主应用程序线程只运行在一个处理器上,不在处理器之间进行切换。
2. 游戏计时器类
在下面的两节中,我们将讨论GameTimer类的实现。
class GameTimer
{
public:
GameTimer();
float TotalTime()const; // 单位为秒