begin fGameState:= TGameState.Paused; Mix_PlayChannel(-1, fSounds[ Ord(TSoundKind.sndGamePause) ], 0); end; TGameState.GameOver: StartNewGame; end; end; end; SDL_JOYBUTTONDOWN : case event.jbutton.button of 0, 1, 2, 3 : fPlayer.Input[Ord(TPlayerInput.Shot)] := true; end; end; end;end;Mudamos o estado do game, mas para que o jogo respeite esta mudanca, e necessario atualizar os objetos somente quando estivermos jogando. Vamos alterar TGame.Update para refletir isto.procedure TGame.Update(const deltaTime : real ) ;begin case fGameState of TGameState.Playing : begin fPlayer.Update( deltaTime ); fEnemies.Update( deltaTime ); fShots.Update( deltaTime ); fExplosions.Update( deltaTime ); if ( fPlayer.Lifes <=0) then begin fGameState := TGameState.GameOver; Mix_PlayChannel(-1, fSounds[ Ord(TSoundKind.sndGameOver) ], 0); end; end; TGameState.Paused : begin end; TGameState.GameOver: begin end; end;end; Agora o jogo realmente para em resposta ao pressionamento da tecla e do botao .Para ficar mais bacana, vamos esmaecer o cenario e exibir um texto por cima informado ao jogador o estado que o jogo se encontra. Vamos aproveitar e tambem criar a tela de game over neste passo. O metodo que precisamos alterar e TGame.DrawGui.procedure TGame.DrawGUI;var rect : TSDL_Rect;begin SDL_SetRenderDrawColor(fRenderer, 255, 255, 0, 255); SDL_RenderDrawLine( fRenderer, 0, round(DEBUG_CELL_SIZE * 1.5), SCREEN_WIDTH, round(DEBUG_CELL_SIZE * 1.5)); rect.x:= 0; rect.y:= 0; rect.h:= round(DEBUG_CELL_SIZE * 1.5); rect.w:= SCREEN_WIDTH; SDL_SetRenderDrawColor(fRenderer, 255, 0, 0, 80); SDL_RenderFillRect( fRenderer, @rect ); fGameText.Draw( Format('SCORE %.6d', [fScore]), 290, 12, fGameFonts.GUI ); rect.x:= 710; rect.y:= 18; rect.h:= 2 *fPlayer.Sprite.Texture.H div 3; rect.w:= 2 *fPlayer.Sprite.Texture.W div 3; SDL_RenderCopy(fRenderer, fPlayer.Sprite.Texture.Data, @fPlayer.Sprite.CurrentFrame.Rect, @rect); fGameText.Draw( Format('%.2d', [fPlayer.Lifes]), 738, 12, fGameFonts.GUI ); case fGameState of TGameState.Paused : begin //obsfuscates the game stage rect.x := 0; rect.y := round( 1.5 * DEBUG_CELL_SIZE) +1; rect.h := SCREEN_HEIGHT - rect.y; rect.w:= SCREEN_WIDTH; SDL_SetRenderDrawColor(fRenderer, 0, 0, 0, 200); SDL_RenderFillRect( fRenderer, @rect ); fGameText.Draw( '***[ PAUSED ]***' , 155, SCREEN_HALF_HEIGHT-24, fGameFonts.GUI64 ); if SDL_NumJoysticks = 0 then fGameText.Draw( 'press to resume', 320, SCREEN_HALF_HEIGHT+25, fGameFonts.DebugNormal ) else fGameText.Draw( 'press to resume', 320, SCREEN_HALF_HEIGHT+25, fGameFonts.DebugNormal ); end; TGameState.GameOver : begin //obsfuscates the game stage rect.x := 0; rect.y := round( 1.5 * DEBUG_CELL_SIZE) +1; rect.h := SCREEN_HEIGHT - rect.y; rect.w:= SCREEN_WIDTH; SDL_SetRenderDrawColor(fRenderer, 50, 0, 0, 200); SDL_RenderFillRect( fRenderer, @rect ); fGameText.DrawModulated( '***[ GAME OVER ]***' , 105, SCREEN_HALF_HEIGHT-24, fGameFonts.GUI64, 255,0,0 ); if SDL_NumJoysticks = 0 then fGameText.Draw( 'press to start a new game', 285, SCREEN_HALF_HEIGHT+25, fGameFonts.DebugNormal ) else fGameText.Draw( 'press to start a new game', 285, SCREEN_HALF_HEIGHT+25, fGameFonts.DebugNormal ); end; end;end;Com isto concluimos as modificacoes planejadas para este post.Implementamos bastante coisa ate aqui e neste ponto temos um game funcional. As caracteristicas basicas que se repetem em todos os games de graficos 2d estao ai. Ja sabemos como exibir sprites animados, como modelar comportamentos utilizando maquinas de estados, como exibir textos baseados em fontes True Type e como tocar sons.Pode nao parecer, mas as ideias e codigos mais avancados sobre os quais iremos nos debrucar nos proximos textos sao, em sua maioria, especializacoes do que vimos ate aqui, por isso e importante que voce entenda bem o conteudos destes quatro primeiros textos.Para finalizar, o video abaixo mostra o projeto que construimos. E possivel ver a tela de pause/resume e game over, as colisoes e a movimentacao dos inimigos. No final, e exibido um gameplay na visao de debug,