Sequencia de introducao do gameBem vindo a quinta parte do nosso mini curso Criando um Game Completo, onde criamos uma versao do classico Space Invaders compativel com Windows e Linux, utilizando aceleracao de hardware para graficos 2D, suporte a joysticks e uma tabela de scores online!No ultimo artigo completamos uma versao jogavel do game. Os sons, as animacoes o tratamento de colisoes, tudo o que planejamos foi implementado com sucesso. Mas ainda falta muita coisa para o game estar, de fato, completo.A imensa maioria do codigo que escrevemos esta contido dentro de uma unica classe: TGame. Isto vinha funcionando bem, mas conforme o game cresce, fica evidente que as classes estao acumulando responsabilidades demais. Com a necessidade de criar outras telas, e preciso isolar algumas tarefas e criar objetos mais genericos para que possamos reutiliza-los em outras partes.Neste post, vamos fazer uma grande refatoracao no codigo e criar nosso proprio motor, de modo que sejamos capaz de realizar tudo o que TGame faz atualmente e comecar a esconder alguns detalhes de nivel mais baixo do SDL. Vamos caminhar rumo a um modelo de programacao menos procedural e mais orientado a eventos, um conceito bem familiar para quem esta acostumado a bibliotecas como VCL e LCL.Espero que apreciem.Abracos!EngineA classe TGame esta sobrecarregada! Ela possui responsabilidades demais. Embora as coisas tenham funcionado bem ate aqui, chegamos em um ponto em que uma refatoracao se faz necessaria.Diagrama de classes do motor que vamos implementarUm jogo nao se resume a tela em que a acao acontece. Sempre ha um lugar onde e possivel ver os creditos, uma tabela de pontuacao, uma introducao e algum tipo de menu que permita que o jogador navegue entre estas telas.Se quisermos criar uma destas novas telas, sera preciso replicar muita coisa que ja escrevemos em TGame. Veja, esta nova tela precisaria de um loop para controlar o tempo, precisaria chamar as rotinas de render e update e precisaria capturar os eventos do SDL para funcionar. Tal como esta, pouco podemos fazer alem de copiar boa parte do codigo e colar em uma nova classe. E preciso criar um mecanismo de abstracao que se responsabilize pelo loop principal e que seja capaz de processar e exibir as nossas telas alem de gerenciar os sons, as texuras e as fontes. Em outras palavras, precisamos arquitetar uma camada de software que abstraia estas tarefas. E exatamente isto que faz um game engine e, agora que temos uma necessidade real, vamos implementar o nosso.Veja o diagrama da figura acima. Estude-o por alguns minutos.Cenas e eventosVamos comecar pela classe TScene e TSceneManager.A classe TScene ira encapsular uma cena no game. Cada cena sabera renderizar a si mesmo e ira se comunicar com o TEngine atraves de eventos. TScene = class strict private fName: string; fOnRender: TRenderEvent; fOnUpdate: TUpdateEvent; fOnKeyUp: TKeyboardEvent; fOnKeyDown: TKeyboardEvent; fOnJoyButtonUp: TJoyButtonEvent; fOnJoyButtonDown: TJoyButtonEvent; fOnJoyAxisMotion: TJoyAxisMotionEvent; fOnCheckCollisions: TEvent; fTJoyButtonEvent: TJoyButtonEvent; fOnQuit: TNotifyEvent; protected fQuitting : boolean; procedure doOnRender(renderer : PSDL_Renderer); virtual; procedure doOnUpdate(const deltaTime : real); virtual; procedure doOnKeyUp(key: TSDL_KeyCode); virtual; procedure doOnKeyDown(key: TSDL_KeyCode); virtual; procedure doOnJoyButtonUp(joystick: SInt32; button: UInt8); virtual; procedure doOnJoyButtonDown(joystick: