Game Engine Basic:Timer(计时器)
之前已经实现了一个简单的查询时钟Clock,这里借助Clock来实现一个Timer。
以达到和Sleep等函数相同功能,但更高精度的效果。
它的用法也比较简单,以下为测试代码:
main.cpp
#include <iostream> #include "Timer.h" int main() { Timer timer; double nowTime; timer.setTickInterval(1); timer.start(); do { nowTime = timer.getRunTime(); printf("当前时间为%lf\n",nowTime); timer.tick(); } while (timer.getRunTime()<4); return 0; }
对比前文Clock中测试Sleep函数的数据,可以看到我们自制的计时器精度有了显著提高。
由此我们可以更精细地控制游戏循环等各种涉及时间的部分。
翻到后文代码部分,我们看到Timer类里有许多函数,
诸如:
start() //初次开启计时
pause() //暂停
resume() //从暂停中恢复
以及许多get类函数,但这并非重点。
真正最核心的函数还是滴答。
tick() //滴答一次
可能一下子不好理解这个滴答,
但是如果联系之前类比的Sleep延时函数就容易理解了。
延时函数:
一般情况下,延时函数实现的原理就是让其一直调用无意义的循环,直到超过设定的时间。
我们这里的滴答就像真正的时钟滴答一下,表面已经走过了一个时间片段,如一秒。
这个时间片段也称滴答间隔可以自由设置,在没超过滴答间隔的时间内,应该继续等待(做无意义循环),直到超过后,
作一些数据处理。
Timer.h
#ifndef __TIMER_H__ #define __TIMER_H__ #include "Clock.h" class Timer { public: Timer(); //开始计时 void start(); //暂停计时 void pause(); //恢复计时 void resume(); //时钟滴答 void tick(); //设置滴答时间间隔 void setTickInterval(double _tickInterval); //获取开始时间点 double getStartPoint(); //获取运行时间 double getRunTime(); //获取是否暂停 bool IsPause(); private: bool isPause; //当前时间点 double nowPoint; //开启计时器时间点 double startPoint; //上次滴答时间点 double preTickPoint; //上次暂停时间点 double prePausePoint; //恢复时间点 double resumePoint; //已暂停时间 double pausedTime; //已运行时间 double runTime; //滴答间隔 double tickInterval; }; #endif // ! __TIMER_H__
Timer.cpp
#include "Timer.h" Timer::Timer():isPause(false),tickInterval(0.001), startPoint(0),preTickPoint(0),prePausePoint(0),resumePoint(0), pausedTime(0),runTime(0){ } void Timer::start() { nowPoint = Clock::get()->time(); startPoint = nowPoint; resumePoint = nowPoint; } void Timer::pause() { if (!isPause) { nowPoint = Clock::get()->time(); prePausePoint = nowPoint; isPause = true; } } void Timer::resume() { if (isPause) { nowPoint = Clock::get()->time(); resumePoint = nowPoint; pausedTime += resumePoint - prePausePoint; isPause = false; } } void Timer::tick() { if (isPause) { return; } do { nowPoint = Clock::get()->time(); } while ((nowPoint-preTickPoint)<tickInterval); preTickPoint = nowPoint; } void Timer::setTickInterval(double _tickInterval) { tickInterval = _tickInterval; } bool Timer::IsPause() { return isPause; } double Timer::getStartPoint() { return startPoint; } double Timer::getRunTime() { nowPoint = Clock::get()->time(); return nowPoint - startPoint - pausedTime; }