-1, SDL_RENDERER_ACCELERATED); if ( fRenderer = nil ) then raise SDLException.Create( SDL_GetError ); flags := IMG_INIT_PNG; result := IMG_Init( flags ); if ( ( result and flags ) <> flags ) then raise SDLImageException.Create( IMG_GetError ); result := TTF_Init; if ( result <> 0 ) then raise SDLTTFException.Create( TTF_GetError ); result := Mix_OpenAudio(44100 div 2, MIX_DEFAULT_FORMAT, 2, 2048); if result < 0 then raise SDLMixerException.Create( Mix_GetError ); fText := TTextManager.Create( fRenderer ); fFonts := TFonts.Create( fRenderer ); fFonts.LoadFonts( FONTS_DIR ); fSounds := TSoundManager.Create; fSounds.LoadSounds(SOUND_DIR);end;Finalmente, podemos utilizar o motor para exibir uma cena.try Engine := TEngine.GetInstance; Engine.Initialize(800, 600, 'Window Title'); Engine.SetActiveScene(myAwsomeScene); Engine.Run; finally Game.Free; Engine.Free; end; Supondo que myAwsomeScene seja uma instancia de TScene, ela ira receber todos as mensagens do SDL que utilizamos ate agora na forma de chamadas a seus eventos equivalentes (aqueles que vimos no comeco desta secao). Bacana nao?Com nosso pequeno motor finalizado, e conveniente criar um conteiner para as varias cenas que um jogo pode ter e e ai que entra a ultima classe do diagrama: a classe TGame. TGame = class strict private fSceneManager : TSceneManager; public constructor Create; destructor Destroy; override; property Scenes : TSceneManager read fSceneManager write fSceneManager; end; E como estamos criando uma versao do Space Invaders...TSpaceInvadersGame = class(TGame) strict private fPlayer : TPlayer; public constructor Create; destructor Destroy; override; end; Criando uma introducaoMuita coisa mudou e muitas coisas novas surgiram da ultima versao do codigo para esta, mas se voce seguir o diagrama de classes do inicio do texto, nao deve ser dificil acompanhar as mudancas. O que importa e que, depois desta refatoracao, agora temos um pequeno motor que vai entregar os eventos de nivel mais baixo para nosso TGame, nos permitindo esquecer por um tempo os detalhes dos varios subsistemas e nos concentrar em escrever uma cena por vez.Veja o video abaixo e perceba como a sequencia de introducao e programada em uma unica classe: TIntroScene e como, depois de carregadas as texturas, a logica e implementada sobrescrevendo os metodos doOnRender e doOnUpdate, que o motor se encarrega de chamar no momento certo.Quando a cena termina, o executamos o metodo doQuit que informa ao motor que acena terminou e este, por sua vez invoca o metodo doOnSceneQuit de TSpaceInvadersGame que se encarrega de carregar a proxima cena.procedure TSpaceInvadersGame.doOnSceneQuit(sender: TObject);var next : TScene;begin if ( sender is TIntroScene ) then begin TIntroScene(sender).Stop; next := Scenes[fSceneMainMenu]; Scenes.Current := next; end; if ( sender is TMainMenuScene ) then begin TMainMenuScene(sender).Stop; next := Scenes[fSceneGamePLay]; Scenes.Current := next; end; if next <> nil then begin TEngine.GetInstance.SetActiveScene(next); next.Start; end;end;A logica da introducao e bem simples.Temos 3 estados, um para cada imagem a ser exibida, e vamos alterar entres eles apos um determinado tempo. Cada uma das imagens possui 3 estagios de exibicao:FADEINA imagem esta aparecendo.O alpha sai de 0 e vai subindo gradualmente ate 255. A duracao deste estagio e controlada pela constante LOGO_FADEIN.VISIBEA imagem esta 100% visivel.O alpha permanece em 255 durante LOGO_VISIBLE milissegundos.FADEOUTA imagem esta desaparecendo.O alpha sai de 255 e vai diminuindo gradualmente ate chegar em 0. A duracao deste estagio e controlada pela