游戏运行机制和时间通常密切相关,通常我们需要一个更高精度的时钟。
这里提供一个Window环境下高精度的Clock类。
它仅提供查询当前时间的功能。
(当前时间指,从它被构造函数初始化以来,到调用time()函数时,经过的时间)。
它的用法很简单,导入Clock.h头文件,
double nowTime = Clock::get()->time();
即将当前时间保存到nowTime变量里。
以下代码通过该函数测试系统提供的Sleep()函数精度
main.cpp
#include <iostream> #include "Clock.h" int main() { double nowTime = 0; do { nowTime = Clock::get()->time(); printf("当前时间为%lf\n",nowTime); Sleep(1000); } while (nowTime<3); return 0; }
每次运行的结果都有较大差别,可以看到系统提供的时间相关的函数精度并不是很高。
由于游戏循环等各种机制依赖于高精度的计时,因此我们有必要尝试自己实现一个Timer(计时器),而Timer的基础就是Clock。
Clock的原理是通过硬件相关的函数来实现的:
QueryPerformanceFrequecy函数可以保存CPU运行频率。
QueryPerformanceCounter函数可以保存CPU当前计数。
将开始记录计数的时间定义为0,当前时间可以通过公式算得:
当前时间 =(当前计数-开始时计数)/运行频率
Clock.h
#ifndef __CLOCK_H__ #define __CLOCK_H__ #include <Windows.h> class Clock { public: //获取时钟单例 static Clock* get(); //获取当前时间 double time(); private: //创建同时,自动记录开始计数以及机器频率 Clock(); //销毁同时,处理instance指针 ~Clock(); private: //时钟单例 static Clock* instance; //本机频率(和CPU相关) LARGE_INTEGER machineFrequency; //开始时的计数 LARGE_INTEGER countStart; }; #endif
Clock.cpp
#include "Clock.h" Clock* Clock::instance = nullptr; Clock::Clock() { //获取机器频率 QueryPerformanceFrequency(&machineFrequency); //获取开始时的计数 QueryPerformanceCounter(&countStart); } Clock* Clock::get() { if (!instance) { instance = new Clock(); } return instance; } double Clock::time(){ LARGE_INTEGER countNow; QueryPerformanceCounter(&countNow); return (((double)countNow.QuadPart) - ((double)countStart.QuadPart)) / ((double)machineFrequency.QuadPart); } Clock::~Clock() { if (instance) { delete instance; instance = nullptr; } }