Modelo do controle usado para os testesBem vindo a segunda 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 joystics e uma tabela de scores online!No ultimo artigo, criamos uma classe para encapsular a logica do game, carregamos algumas imagens para a memoria e exibimos o primeiro inimigo na tela. Seguiremos, agora, com a animacao dos sprites e a movimentacao do jogador atraves do teclado ou do joystick.Vamos la!Sprites e Animacao (sprite based)No codigo desenvolvido na versao anterior, armazenamos as texturas em um array de PSDL_Texture dentro de TGame e passamos o ponteiro da textura para cada sprite instanciado.Isto funciona, mas ha um problema. O PSDL_Texture e implementado na biblioteca como um ponteiro nao tipado ( void * ), logo nao ha como o sprite saber as dimensoes da textura e acabamos enchendo o codigo de numeros magicos quee precisamos eliminar. Comecaremos criado uma classe com estas informacoes para representar uma textura e, em seguida vamos alterar o codigo de carga das imagens para devolver uma instancia dessa nova classe.TSpriteKind = ( EnemyA = 0, EnemyB = 1, EnemyC = 2, EnemyD = 3, Player = 4, Bunker = 5, Garbage = 6, Explosion = 7, ShotA = 8, Leds = 9);(...)TTexture = class W : integer; H : integer; Data: PSDL_Texture; procedure Assign( pTexure: TTexture );end;(...)procedure TTexture.Assign(pTexure: TTexture);begin self.W := pTexure.W; self.H := pTexure.H; self.Data := pTexure.Data;end;(...)TGame = classprivate fRunning : boolean; fWindow : PSDL_Window; fWindowSurface : PSDL_Surface; fRenderer : PSDL_Renderer; fTextures : array of TTexture; procedure LoadTextures; procedure FreeTextures;(...)function TGame.LoadPNGTexture( const fileName: string ): TTexture;const IMAGE_DIR = '.\assets\images\';var temp : PSDL_Surface;begin result := TTexture.Create; result.W := 0; result.H := 0; result.Data := nil; try temp := IMG_Load( PAnsiChar( IMAGE_DIR + fileName ) ); if ( temp = nil ) then raise SDLException.Create( SDL_GetError ) else begin result.W := temp^.w; result.H := temp^.h; result.Data := SDL_CreateTextureFromSurface( fRenderer, temp ); if ( result.Data = nil ) then raise SDLImageException.Create( IMG_GetError ); end; finally SDL_FreeSurface( temp ); end;end;(...)procedure TGame.LoadTextures;begin SetLength(fTextures, Ord( High( TSpriteKind ) ) +1 ); fTextures[ ord(TSpriteKind.EnemyA) ] := LoadPNGTexture( 'enemy_a.png' ); fTextures[ ord(TSpriteKind.EnemyB) ] := LoadPNGTexture( 'enemy_b.png' ); fTextures[ ord(TSpriteKind.EnemyC) ] := LoadPNGTexture( 'enemy_c.png' ); fTextures[ ord(TSpriteKind.EnemyD) ] := LoadPNGTexture( 'enemy_d.png' ); fTextures[ ord(TSpriteKind.Player) ] := LoadPNGTexture( 'player.png' ); fTextures[ ord(TSpriteKind.Bunker) ] := LoadPNGTexture( 'bunker.png' ); fTextures[ ord(TSpriteKind.Garbage)] := LoadPNGTexture( 'garbage.png' ); fTextures[ ord(TSpriteKind.Explosion)] := LoadPNGTexture( 'explosion.png' ); fTextures[ ord(TSpriteKind.ShotA) ] := LoadPNGTexture( 'shot_a.png' ); fTextures[ ord(TSpriteKind.Leds) ] := LoadPNGTexture( 'leds.png' );end; procedure TGame.FreeTextures;var i: integer;begin for i:= low(fTextures) to High(fTextures) do SDL_FreeSurface( fTextures[ i ].Data ); SetLength(fTextures, 0);end;Veja que criamos mais uma entrada registro TSpriteKind para armazenar uma imagem a mais - um led que utilizaremos mais a frente. Seguimos com a definicao TTexture que, alem de um ponteiro para a textura, possui variaveis para armazenar a as dimensoes da imagem para qual TTexture.Data aponta. Substituimos campo fSprites por fTextures, e os metodos LoadSprites e FreeSprirtes viraram, respectivamente, LoadTextures e FreeTextures. Verifique seu codigo e faca as alteracoes