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

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

#ifndef GAMETIMER_H
#define GAMETIMER_H

class 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,在需要使用的时候调用就可以了。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值