任何类型的游戏API的另一个重要部分是处理时间的能力。在本教程中,我们将制作一个我们可以重新启动的计时器。
//Using SDL, SDL_image, SDL_ttf, standard IO, strings, and string streams
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdio.h>
#include <string>
#include <sstream>
在本教程中,我们将使用字符串流,并且必须包含sstream头,它应该是C++编译器的标准配置。
bool loadMedia()
{
//Loading success flag
bool success = true;
//Open the font
gFont = TTF_OpenFont( "22_timing/lazy.ttf", 28 );
if( gFont == NULL )
{
printf( "Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError() );
success = false;
}
else
{
//Set text color as black
SDL_Color textColor = { 0, 0, 0, 255 };
//Load prompt texture
if( !gPromptTextTexture.loadFromRenderedText( "Press Enter to Reset Start Time.", textColor ) )
{
printf( "Unable to render prompt texture!\n" );
success = false;
}
}
return success;
}
正如[字体渲染教程]中提到的,你要尽量减少渲染文字的次数。我们将有一个纹理来提示输入,还有一个纹理以毫秒为单位显示当前时间。时间纹理每一帧都会改变,所以我们每一帧都要渲染,但提示纹理不会改变,所以我们可以在文件加载函数中渲染一次。
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//Set text color as black
SDL_Color textColor = { 0, 0, 0, 255 };
//Current time start time
Uint32 startTime = 0;
//In memory text stream
std::stringstream timeText;
在进入主循环之前,我们要声明一些变量。我们要注意的两个变量是startTime
变量(这是一个32bits的无符号整数)和timeText
变量,它是一个字符串流。
对于那些从来没有使用过字符串流的人来说,只需要知道它们的功能就像iostreams一样,只不过不是向控制台读写,而是允许你向内存中的字符串读写。当我们在程序中进一步看到它们的使用时,就会更容易理解了。
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
//Reset start time on return keypress
else if( e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_RETURN )
{
startTime = SDL_GetTicks();
}
}
有一个名为SDL_GetTicks[1]的函数,该函数返回自程序启动以来的时间(以毫秒为单位)。对于此演示,我们将拥有一个定时器,该定时器将在每次按回车键时重新启动。
还记得我们如何在程序启动时将开始时间初始化为0吗?这意味着定时器的时间仅是SDL_GetTicks
返回程序开始以来的当前时间。如果我们要在SDL_GetTicks
为5000毫秒(5秒)时重新启动定时器,那么当前时间为10,000毫秒-开始时间将是10000减去5000将是5000毫秒。因此,即使SDL_GetTicks
包含的定时器尚未重新启动,我们也可以让定时器跟踪相对的开始时间并重置其开始时间。
//Set text to be rendered
timeText.str( "" );
timeText << "Milliseconds since start time " << SDL_GetTicks() - startTime;
这里使用的是我们的字符串流。首先用一个空字符串调用str来初始化它为空。然后我们把它当作cout,并向它打印 "自启动时间以来的毫秒"和当前时间减去相对启动时间,这样它就会打印自上次启动定时器以来的时间。
//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
gPromptTextTexture.render( ( SCREEN_WIDTH - gPromptTextTexture.getWidth() ) / 2, 0 );
gTimeTextTexture.render( ( SCREEN_WIDTH - gPromptTextTexture.getWidth() ) / 2, ( SCREEN_HEIGHT - gPromptTextTexture.getHeight() ) / 2 );
//Update screen
SDL_RenderPresent( gRenderer );
最后我们将提示纹理和时间纹理渲染到屏幕上。
在 这里[2]下载本教程的媒体和源代码。
原文链接[3]
「关注我的公众号:编程之路从0到1」
[1]
SDL_GetTicks: http://wiki.libsdl.org/SDL_GetTicks
[2]
这里: http://www.lazyfoo.net/tutorials/SDL/22_timing/22_timing.zip
[3]
原文链接: http://www.lazyfoo.net/tutorials/SDL/22_timing/index.php