Continuando nossa série de artigos traduzidos do site lazyfoo.net, agora veremos como realizar uma das tarefas mais comuns em jogos: ler a entrada de dados do teclado. Nesse artigo estaremos obtendo o texto usando os recursos de entrada de dados e manipulação da área de trabalho do SDL 2.
//Main loop flag bool quit = false; //Event handler SDL_Event e; //Set text color as black SDL_Color textColor = { 0, 0, 0, 0xFF }; //The current input text. std::string inputText = "Some Text"; gInputTextTexture.loadFromRenderedText( inputText.c_str(), textColor ); //Enable text input SDL_StartTextInput();
Antes de entrarmos no loop principal declaramos uma string para armazenar nosso texto e renderiza-lo em um textura. Chamamos então SDL_StartTextInput para que as funcionalidades de entrada de texto do SDL sejam ativadas.
//While application is running while( !quit ) { //The rerender text flag bool renderText = false; //Handle events on queue while( SDL_PollEvent( &e ) != 0 ) {
Queremos apenas atualizar a entrada de texto quando precisarmos, assim teremos uma flag para indicar se precisamos atualizar a textura.
//Special key input else if( e.type == SDL_KEYDOWN ) { //Handle backspace if( e.key.keysym.sym == SDLK_BACKSPACE && inputText.length() > 0 ) { //lop off character inputText.pop_back(); renderText = true; } //Handle copy else if( e.key.keysym.sym == SDLK_c && SDL_GetModState() & KMOD_CTRL ) { SDL_SetClipboardText( inputText.c_str() ); } //Handle paste else if( e.key.keysym.sym == SDLK_v && SDL_GetModState() & KMOD_CTRL ) { inputText = SDL_GetClipboardText(); renderText = true; } }
Haverão alguns teclas especiais que queremos lidar. Quando o usuário pressiona a barra de espaço, queremos remover o último caractere da string.
Quando o usuário estive pressionando control e apertar a tecla c, queremos copiar o texto atual para a área de transferência usando SDL_SetClipboardText. Você pode verificar se a tecla control está pressionada com SDL_GetModState.
Quando o usuário usa a combinação ctrl + v, queremos pegar o texto da área de transferência usando SDL_GetClipboardText. Também observe que sempre que alterarmos o conteúdo da string ajustamos a flag de atualização.
//Special text input event else if( e.type == SDL_TEXTINPUT ) { //Not copy or pasting if( !( ( e.text.text[ 0 ] == 'c' || e.text.text[ 0 ] == 'C' ) && ( e.text.text[ 0 ] == 'v' || e.text.text[ 0 ] == 'V' ) && SDL_GetModState() & KMOD_CTRL ) ) { //Append character inputText += e.text.text; renderText = true; } } }
Com a entrada de texto ativada, toda vez que você pressionar uma tecla também será gerado um evento SDL_TextInputEvents o que simplifica as coisas como o pressionamento da tecla shift e do caps lock. Aqui primeiro queremos verificar que não estamos lendo um evento control c/control v pois iremos ignorar esses, já que já lidamos com esses eventos. Se não se tratar de um evento desses tipos, nós anexamos o caractere em nossa string.
//Rerender text if needed if( renderText ) { //Text is not empty if( inputText != "" ) { //Render new text gInputTextTexture.loadFromRenderedText( inputText.c_str(), textColor ); } //Text is empty else { //Render space texture gInputTextTexture.loadFromRenderedText( " ", textColor ); } }
Se a flag de atualização do texto a ser renderizado foi ajustada, renderizamos a textura novamente. Um pequeno ajuste que temos aqui é que se tivermos uma string vazia, renderizamos uma espaço, pois SDL_ttf não renderiza uma string vazia.
//Clear screen SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF ); SDL_RenderClear( gRenderer ); //Render text textures gPromptTextTexture.render( ( SCREEN_WIDTH - gPromptTextTexture.getWidth() ) / 2, 0 ); gInputTextTexture.render( ( SCREEN_WIDTH - gInputTextTexture.getWidth() ) / 2, gPromptTextTexture.getHeight() ); //Update screen SDL_RenderPresent( gRenderer ); }
No final do loop principal nós renderizamos o texto sendo exibido e a entrada de texto.
//Disable text input SDL_StopTextInput();
Baixe os arquivo de mídia e do código fonte para o exemplo desse artigo aqui.