DX12框架里面的GameTimer类实现解释

来源:互联网 发布:mac管理员名字忘记 编辑:程序博客网 时间:2024/04/30 03:19

GameTimer是DX12框架里面一个游戏时间控制的类,主要实现了计算两帧之间的时间差以及游戏的总运行时间(不算暂停的时间)。原理是采用获取WINDOS提供的高精度计时器进行计算。
首先看一下头文件:

#ifndef GAMETIMER_H#define GAMETIMER_Hclass GameTimer{public:    GameTimer();    float TotalTime()const; // 运行的总时间(减去了暂停时间)    float DeltaTime()const; // 两帧之间的时间差    void Reset(); // 重置    void Start(); // 暂停之后重新开始计时    void Stop();  // 暂停计时    void Tick();  // 每帧调用从而计算出前一帧和这一帧的时间差private:    double mSecondsPerCount;    double mDeltaTime;    __int64 mBaseTime;    __int64 mPausedTime;    __int64 mStopTime;    __int64 mPrevTime;    __int64 mCurrTime;    bool mStopped;};#endif // GAMETIMER_H

构造函数

GameTimer::GameTimer(): mSecondsPerCount(0.0), mDeltaTime(-1.0), mBaseTime(0),   mPausedTime(0), mPrevTime(0), mCurrTime(0), mStopped(false){    __int64 countsPerSec;    QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec);    mSecondsPerCount = 1.0 / (double)countsPerSec;}

初始化所有变量,注意mDeltaTime赋值的是-1.QueryPerformanceFrequency是Windos里面用来返回硬件支持的高精度计数器的频率的API,详细解释点这里。所以mSecondsPerCount 便是计数器两个数之间的时间差。

void Reset()

void GameTimer::Reset(){    __int64 currTime;    QueryPerformanceCounter((LARGE_INTEGER*)&currTime);    mBaseTime = currTime;    mPrevTime = currTime;    mStopTime = 0;    mStopped  = false;}

重置变量,类似于初始化,在应用程序开始初始化的时候调用一次,QueryPerformanceCounter是WINDOS用来返回当前计数器的值的API,返回值是整数,详细介绍点这里

void Stop()

void GameTimer::Stop(){    if( !mStopped )    {        __int64 currTime;        QueryPerformanceCounter((LARGE_INTEGER*)&currTime);        mStopTime = currTime;        mStopped  = true;    }}

将游戏暂停,存储暂停的时候的计数器的计数到mStopTime 中。

void Start()

void GameTimer::Start(){    __int64 startTime;    QueryPerformanceCounter((LARGE_INTEGER*)&startTime);    if( mStopped )    {        mPausedTime += (startTime - mStopTime);         mPrevTime = startTime;        mStopTime = 0;        mStopped  = false;    }}

当游戏暂停时调用这个函数继续开始计数,其中mPausedTime 会把每次暂停时间累加起来。
这里写图片描述

float TotalTime()const

float GameTimer::TotalTime()const{    if( mStopped )    {        return (float)(((mStopTime - mPausedTime)-mBaseTime)*mSecondsPerCount);    }       else    {        return (float)(((mCurrTime-mPausedTime)-mBaseTime)*mSecondsPerCount);    }}

如果暂停了,我们返回暂停时从WINDOS获取的计数减去之前暂停的总计数减去开始游戏时从WINDOS获取的计数,
这里写图片描述
如果是在运行中就用当前从WINDOS获取的计数减去之前暂停的总计数减去开始游戏时从WINDOS获取的计数。
这里写图片描述
其中暂停的总计数为每次暂停的计数累加。

void Tick()

void GameTimer::Tick(){    if( mStopped )    {        mDeltaTime = 0.0;        return;    }    __int64 currTime;    QueryPerformanceCounter((LARGE_INTEGER*)&currTime);    mCurrTime = currTime;    mDeltaTime = (mCurrTime - mPrevTime)*mSecondsPerCount;    mPrevTime = mCurrTime;    if(mDeltaTime < 0.0)    {        mDeltaTime = 0.0;    }}

如果游戏是暂停的直接那么就不存在帧与帧之间的时间差,所以直接返回0。否则的话用当前的计数器的值减去上一帧的计数器的值,并乘上计数器两个数之间的时间差(mSecondsPerCount)。这个值在构造函数的时候获得,这个值受电脑性能的影响。
在计算出当前帧与上一帧的时间差之后,把当前帧的计数器的值保存到上一帧的值(mPrevTime )里面为下一帧计算做准备。
这个函数需要在游戏的每一帧调用

float DeltaTime()const

float GameTimer::DeltaTime()const{    return (float)mDeltaTime;}

返回mDeltaTime,在需要使用的时候调用就可以了。

1 0