:= Length(fFrames); case fAnimationType of TSpriteAnimationType.NoLoop: begin inc(fFrameIndex, count); if fFrameIndex > framesLength-1 then fFrameIndex := framesLength-1 else if (fFrameIndex < 0) then fFrameIndex:= 0; end; TSpriteAnimationType.Circular : begin fFrameIndex := (fFrameIndex + count) mod framesLength; end; end;end;Apesar do tamanho da classe, o codigo de TSprite e muito simples e dispensa maiores explicacoes exceto, talvez, pelo metodo: TSprite.Update.As animacoes, como sabemos, sao implementadas em computacao grafica como a mudanca de estado em funcao do tempo ou seja, para cada ponto no tempo, a contar do inicio do programa, alteramos a variaveis de todos os objetos para refletir seu estado naquele momento. Para que isto funcione, precisamos contar a passagem do tempo e atualizar nossos objetos periodicamente. Este e o intuito de TSprite.Update. Ele recebe em deltaTime, a quantidade de tempo decorrida desde a ultima atualizacao. Este tempo e passado em fracoes de segundos.Para implementar a contagem do tempo, vamos alterar nosso game loop e adicionar um novo metodo em TGame.procedure TGame.Run;var deltaTime : real; thisTime, lastTime : UInt32;begin deltaTime := 0.0; thisTime := 0; lastTime := 0; fRunning := true; while fRunning do begin thisTime := SDL_GetTicks; deltaTime := real((thisTime - lastTime) / 1000); lastTime := thisTime; HandleEvents; Update( deltaTime ); Render; SDL_Delay(1); end;end;(...)procedure TGame.Update(const deltaTime : real ) ;var i: integer;begin for i:= 0 to High(fEnemies) do fEnemies[i].Update(deltaTime);end;A funcao SDL_GetTicks fornece a chave para a logica de contagem do tempo decorrido entre cada iteracao do loop. Ela retorna a quantidade de milisegundos desde a inicializacao do SDL. Com esta informacao, calculamos a o intervalo detaTime com uma subtracao ( thisTime - lastTime ) e dividimos o resultado por 1000 para converter o valor para a escala dos segundos. Feito isto, sabemos o quanto devemos avancar o estado dos objetos na linha do tempo e a funcao TGame.Update e responsavel por isto, iterando por todos os objetos do jogo e chamando a versao adequada de TGameObject.Update para cada um ( TSprite.Update, no caso dos sprites explicados nos paragrafos anteriores ).Ao final do loop, note a chamada de SDL_Delay(1). Ela faz com que o programa aguarde 1ms antes de prosseguir para garantir que o intervalo entre as chamadas sempre seja maior 0ms, evitando assim, uma divisao por zero no nosso calculo e, de quebra, dando um tempinho para o processado, evitando um consumo desnecessariamente alto de cpu.Vamos seguir alterando as classes do game para que todo TGameObject tenha um metodo Update, para que TEnemy possua um Sprite e para que TEnemyA saiba desenhar a si mesmo como um sprite animado.TGameObject = classstrict protected fRenderer : PSDL_Renderer;public Position : TPoint; constructor Create( const aRenderer: PSDL_Renderer ); virtual; procedure Update(const deltaTime : real ); virtual; abstract; procedure Draw; virtual; abstract;end;TEnemy = class( TGameObject )private fSprite : TSprite;public HP : integer; constructor Create( const aRenderer: PSDL_Renderer ); override; destructor Destroy; override; procedure Update(const deltaTime : real); override; property Sprite: TSprite read fSprite;end; (...){ TEnemy Implementation }constructor TEnemy.Create(const aRenderer: PSDL_Renderer);begin inherited Create(aRenderer); fSprite := TSprite.Create;end;destructor TEnemy.Destroy;begin fSprite.Free; inherited Destroy;end;procedure TEnemy.Update(const deltaTime : real);begin Sprite.Update(deltaTime);end;(...)procedure TEnemyA.Draw;var source, destination : TSDL_Rect;begin if ( HP > 0 ) and (