//Timer类
class Timer
{
private:
//计时器启动时的时间
int startTicks;
//计时器暂停时保存的滴答数
int pausedTicks;
//计时器状态
bool paused;
bool started;
public:
//初始化变量
Timer();
//各种时钟动作
void start();
void stop();
void pause();
void unpause();
//获取计时器时间
int get_ticks();
//检查计时器状态
bool is_started();
bool is_paused();
};
这里我们有timer类的纲要。
"startTicks"是计时器的起始点,"pausedTicks"是计时器暂停时所保存的时间。
构造函数对变量进行了初始化,我很确定你能明白
函数
"startTicks"是计时器的起始点,"pausedTicks"是计时器暂停时所保存的时间。
构造函数对变量进行了初始化,我很确定你能明白
start(), stop(), pause(), 和 unpause() 函数的作用。
函数
get_ticks() 可获取计时器的时间,以毫秒为单位。is_started() 检查计时器是否已经启动,is_paused() 检查计时器是否已暂停。Timer::Timer()
{
//初始化各种变量
startTicks = 0;
pausedTicks = 0;
paused = false;
started = false;
}
这里我们有一个构造函数,它初始化了许多变量。这没有什么需要解释的。
void Timer::start()
{
//启动计时器
started = true;
//将计时器设为非暂停状态
paused = false;
//获取当前时钟时间
startTicks = SDL_GetTicks();
}
现在当我们启动计时器时,我们将started状态设为true,将计时器设为非暂停状态,然后我们使用
SDL_GetTicks()获得当前时间,并将它设为计时器的启动时间。void Timer::stop()
{
//停止计时器
started = false;
//将计时器设为非暂停状态
paused = false;
}
当我们停止计时器的时候,我们将started状态设为false,并将计时器设为非暂停状态。
int Timer::get_ticks()
{
//如果计时器正在运行
if( started == true )
{
//如果计时器暂停中
if( paused == true )
{
//返回计时器暂停时的滴答数
return pausedTicks;
}
else
{
//返回当前时间减去启动时间的差值
return SDL_GetTicks() - startTicks;
}
}
//如果计时器没有在运行
return 0;
}
这里我们有获取计时器时间的函数。
首先,我们检查一下计时器是否在运行。如果是的话,然后检查它是否处于暂停状态。
如果计时器暂停中,我们返回计时器暂停时所保存的时间。我们将在后面讨论暂停和取消暂停。
如果计时器没有暂停,我们返回从计时器启动到当前的时间差。你可以看出来,这与上一课中所提到的公式完全相同。
如果计时器没有运行,函数将返回0。
首先,我们检查一下计时器是否在运行。如果是的话,然后检查它是否处于暂停状态。
如果计时器暂停中,我们返回计时器暂停时所保存的时间。我们将在后面讨论暂停和取消暂停。
如果计时器没有暂停,我们返回从计时器启动到当前的时间差。你可以看出来,这与上一课中所提到的公式完全相同。
如果计时器没有运行,函数将返回0。
void Timer::pause()
{
//如果计时器正在运行但没有暂停
if( ( started == true ) && ( paused == false ) )
{
//暂停计时器
paused = true;
//计算暂停时的滴答数
pausedTicks = SDL_GetTicks() - startTicks;
}
}
现在当我们想要暂停计时器时,首先我们检查一下计时器是否正在运行并且还没有暂停,如果我们可以暂停计时器,我们将paused状态设为true,并且将计时器的时间保存在"pausedTicks"中。
void Timer::unpause()
{
//如果计时器暂停中
if( paused == true )
{
//取消暂停
paused = false;
//重置开始时间
startTicks = SDL_GetTicks() - pausedTicks;
//重置暂停时间
pausedTicks = 0;
}
}
当我们想要取消暂停时,我们先检查一下计时器是否暂停中。
如果是的,我们将paused状态设为false,然后将开始时间设为当前时钟时间减去计时器暂停时保存时间之差。
最后,我们将"pausedTicks"设为0,没有什么真正的原因,我只是不喜欢杂散变量。
如果是的,我们将paused状态设为false,然后将开始时间设为当前时钟时间减去计时器暂停时保存时间之差。
最后,我们将"pausedTicks"设为0,没有什么真正的原因,我只是不喜欢杂散变量。
bool Timer::is_started()
{
return started;
}
bool Timer::is_paused()
{
return paused;
}
这里是检查计时器状态的函数。我很确信你能搞清楚它们是做什么的。
//新建计时器
Timer myTimer;
//生成信息表面
startStop = TTF_RenderText_Solid( font, "Press S to start or stop the timer", textColor );
pauseMessage = TTF_RenderText_Solid( font, "Press P to pause or unpause the timer", textColor );
现在在我们的main函数中,在我们完成初始化和文件加载后,我们声明了一个计时器对象并渲染了我们的信息表面。
//启动计时器
myTimer.start();
//当用户还没退出时
while( quit == false )
{
在我们进入主循环前,我们先启动计时器。
//当有事件需要处理
while( SDL_PollEvent( &event ) )
{
//如果有一个按键被按下
if( event.type == SDL_KEYDOWN )
{
//如果“s”被按下
if( event.key.keysym.sym == SDLK_s )
{
//如果计时器在运行
if( myTimer.is_started() == true )
{
//停止计时器
myTimer.stop();
}
else
{
//启动计时器
myTimer.start();
}
}
这里我们处理了按键按下的事件。当“s”被按下时,如果计时器还在运行,就将它停止,否则就启动它。
//如果“p”被按下
if( event.key.keysym.sym == SDLK_p )
{
//如果计时器暂停中
if( myTimer.is_paused() == true )
{
//取消暂停
myTimer.unpause();
}
else
{
//暂停计时器
myTimer.pause();
}
}
}
现在,当“p”被按下,如果计时器正在暂停中,我们就取消其暂停,否则我们将其暂停。
//保存计时器时间的字符串
std::stringstream time;
//将计时器的时间转换为字符串
time << "Timer: " << myTimer.get_ticks() / 1000.f;
//渲染时间表面
seconds = TTF_RenderText_Solid( font, time.str().c_str(), textColor );
//应用时间表面
apply_surface( ( SCREEN_WIDTH - seconds->w ) / 2, 0, seconds, screen );
//释放时间表面
SDL_FreeSurface( seconds );
//更新窗口
if( SDL_Flip( screen ) == -1 )
{
return 1;
}
}
在事件处理完并且背景表面和信息表面都blit完毕后,我们将计时器的时间显示在屏幕上。
首先,我们创建一个string stream对象,然后我们将计时器的时间放入这个string stream。由于我们需要显示的计时器的时间是以秒为单位,又因为1秒=1000毫秒,所以我们将时间除以1000。
下面,我们使用保存着时间的string创建一个表面。然后这个新建的显示了计时器时间的表面被blit到窗口上,接着我们将这个表面释放,因为我们已经用完它了。之后,窗口被更新,我们继续运行主循环。
首先,我们创建一个string stream对象,然后我们将计时器的时间放入这个string stream。由于我们需要显示的计时器的时间是以秒为单位,又因为1秒=1000毫秒,所以我们将时间除以1000。
下面,我们使用保存着时间的string创建一个表面。然后这个新建的显示了计时器时间的表面被blit到窗口上,接着我们将这个表面释放,因为我们已经用完它了。之后,窗口被更新,我们继续运行主循环。