SDL程式設計入門(23)高階定時器
高階定時器
現在我們已經做了一個用SDL做的基本計時器,是時候做一個可以啟動/停止/暫停的計時器了。
//The application time based timer
class LTimer
{
public:
//Initializes variables
LTimer();
//各種時鐘操作
void start();
void stop();
void pause();
void unpause();
//獲取定時器的時間
Uint32 getTicks();
//檢查定時器的狀態
bool isStarted();
bool isPaused();
private:
//定時器開始時的時間
Uint32 mStartTicks;
//定時器暫停時的時間
Uint32 mPausedTicks;
//定時器狀態
bool mPaused;
bool mStarted;
};
對於這些新功能,我們將建立一個定時器類。 它具有啟動/停止/暫停/取消暫停計時器並檢查其狀態的所有基本功能。在資料成員方面,我們有像之前一樣的開始時間,有一個變數來儲存暫停時的時間,還有狀態標誌來跟蹤定時器是在執行還是暫停。
LTimer::LTimer()
{
//Initialize the variables
mStartTicks = 0;
mPausedTicks = 0;
mPaused = false;
mStarted = false;
}
我們的建構函式初始化內部資料成員。
void LTimer::start()
{
//Start the timer
mStarted = true;
//Unpause the timer
mPaused = false;
//Get the current clock time
mStartTicks = SDL_GetTicks();
mPausedTicks = 0;
}
start函式設定啟動和暫停標誌,獲取定時器的啟動時間,並將暫停時間初始化為0,對於這個定時器,如果我們想重新啟動它,只需再次呼叫start即可。由於我們可以在定時器暫停和/或執行的情況下啟動它,所以我們應該確保清除暫停的資料。
void LTimer::stop()
{
//Stop the timer
mStarted = false;
//Unpause the timer
mPaused = false;
//Clear tick variables
mStartTicks = 0;
mPausedTicks = 0;
}
stop函式基本上重新初始化了所有的變數。
void LTimer::pause()
{
//If the timer is running and isn't already paused
if( mStarted && !mPaused )
{
//Pause the timer
mPaused = true;
//Calculate the paused ticks
mPausedTicks = SDL_GetTicks() - mStartTicks;
mStartTicks = 0;
}
}
暫停時,我們要檢查定時器是否在執行,因為暫停一個沒有啟動的定時器是沒有意義的。如果定時器正在執行,我們設定暫停標誌,將定時器暫停的時間儲存在mPausedTicks中,並重新設定啟動時間。
void LTimer::unpause()
{
//If the timer is running and paused
if( mStarted && mPaused )
{
//Unpause the timer
mPaused = false;
//Reset the starting ticks
mStartTicks = SDL_GetTicks() - mPausedTicks;
//Reset the paused ticks
mPausedTicks = 0;
}
}
因此,當我們取消暫停定時器時,要確保定時器正在執行和暫停,因為我們不能取消一個停止或執行的定時器。我們將暫停標誌設定為false,並設定新的啟動時間。
比如說,如果你在SDL_GetTicks()
報告5000毫秒時啟動定時器,然後在10000毫秒時暫停。這意味著暫停時的相對時間是5000ms。如果我們要在SDL_GetTicks
為20000時取消暫停,則新的開始時間將為20000-5000ms或15000ms。 這樣,相對時間仍將與當前SDL_GetTicks
時間相距5000ms。
Uint32 LTimer::getTicks()
{
//The actual timer time
Uint32 time = 0;
//If the timer is running
if( mStarted )
{
//If the timer is paused
if( mPaused )
{
//Return the number of ticks when the timer was paused
time = mPausedTicks;
}
else
{
//Return the current time minus the start time
time = SDL_GetTicks() - mStartTicks;
}
}
return time;
}
獲取時間是有點棘手的,因為我們的定時器可以執行、暫停或停止。如果定時器是停止的,我們只是返回初始的0值。如果定時器暫停,我們返回暫停時儲存的時間。如果定時器正在執行而不是暫停,我們返回相對於它開始時的時間。
bool LTimer::isStarted()
{
//Timer is running and paused or unpaused
return mStarted;
}
bool LTimer::isPaused()
{
//Timer is running and paused
return mPaused && mStarted;
}
在這裡,我們有一些訪問函式來檢查定時器的狀態。
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//Set text color as black
SDL_Color textColor = { 0, 0, 0, 255 };
//The application timer
LTimer timer;
//In memory text stream
std::stringstream timeText;
在進入主迴圈之前,我們宣告一個定時器物件和一個字串流來將時間值變成文字。
else if( e.type == SDL_KEYDOWN )
{
//Start/stop
if( e.key.keysym.sym == SDLK_s )
{
if( timer.isStarted() )
{
timer.stop();
}
else
{
timer.start();
}
}
//Pause/unpause
else if( e.key.keysym.sym == SDLK_p )
{
if( timer.isPaused() )
{
timer.unpause();
}
else
{
timer.pause();
}
}
}
當我們按s鍵時,我們檢查定時器是否啟動。如果啟動了,我們就停止它。如果沒有,我們就啟動它。當我們按p鍵時,我們檢查定時器是否暫停。如果是,我們就取消暫停。否則,我們將暫停它。
//Set text to be rendered
timeText.str( "" );
timeText << "Seconds since start time " << ( timer.getTicks() / 1000.f ) ;
//Render text
if( !gTimeTextTexture.loadFromRenderedText( timeText.str().c_str(), textColor ) )
{
printf( "Unable to render time texture!\n" );
}
//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );
//Render textures
gStartPromptTexture.render( ( SCREEN_WIDTH - gStartPromptTexture.getWidth() ) / 2, 0 );
gPausePromptTexture.render( ( SCREEN_WIDTH - gPausePromptTexture.getWidth() ) / 2, gStartPromptTexture.getHeight() );
gTimeTextTexture.render( ( SCREEN_WIDTH - gTimeTextTexture.getWidth() ) / 2, ( SCREEN_HEIGHT - gTimeTextTexture.getHeight() ) / 2 );
//Update screen
SDL_RenderPresent( gRenderer );
在渲染之前,我們將當前時間寫入一個字串流。我們之所以將其除以1000,是因為我們要的是秒,而每秒有1000毫秒。
之後我們將文字渲染成紋理,最後將所有的紋理繪製到螢幕上。
在 這裡下載本教程的媒體和原始碼。
關注我的公眾號:程式設計之路從0到1
相關文章
- SDL程式設計入門(26)運動程式設計
- SDL程式設計入門(25)限制幀率程式設計
- SDL程式設計入門(29)圓形碰撞檢測程式設計
- SDL程式設計入門(28)每畫素碰撞檢測程式設計
- Oracle 高階程式設計 01 ~Oracle程式設計
- C#與.NET入門之C# 8.0和.NET Core 3.0高階程式設計C#程式設計
- Python 高階程式設計:深入探索高階程式碼實踐Python程式設計
- 低階程式設計師和高階程式設計師的區別程式設計師
- Java程式設計指南:高階技巧解析 - Excel單元格樣式的程式設計設定Java程式設計Excel
- Go Web 程式設計入門--路由器GoWeb程式設計路由器
- 三菱FX PLC入門之定時器和計數器定時器
- windows核心程式設計--DLL高階Windows程式設計
- Javascript高階程式設計 備忘JavaScript程式設計
- C++高階程式設計pdfC++程式設計
- JavaScript高階程式設計筆記JavaScript程式設計筆記
- 重讀《JavaScript高階程式設計》JavaScript程式設計
- Python高階程式設計技巧Python程式設計
- shell程式設計-高階變數程式設計變數
- 程式設計師程式設計入門一定知道!程式設計師需要學什麼?程式設計師
- 網路程式設計定時器二:使用時間輪程式設計定時器
- 入門程式碼程式設計程式設計
- Shell 程式設計入門程式設計
- shell程式設計入門程式設計
- 高階bash指令碼程式設計(1)指令碼程式設計
- 程式設計和網路程式設計入門程式設計
- shell程式設計,實戰高階進階教學程式設計
- .NET簡談——跨進高階程式設計門檻的必經之路程式設計
- unix環境高階程式設計(中)-程式篇程式設計
- JavaScript 高階函式快速入門JavaScript函式
- .NET 入門到高階路線
- React 高階元件(HOC)入門指南React元件
- unix環境高階程式設計(下)-高階IO和程式間通訊篇程式設計
- 網路程式設計定時器三:使用最小堆程式設計定時器
- 嵌入式作業5.1 定時器程式設計定時器程式設計
- 【北京】誠聘java程式設計師和高階程式設計師Java程式設計師
- SDL3 入門(5):紋理渲染
- 《C# 8.0和.NET Core 3.0高階程式設計(第4版)》之“C# 與 .NET 入門 ”C#程式設計
- 遊戲程式設計入門指南遊戲程式設計