Exatamente os retangulos que definem os limites de cada frame que nossa classe de sprite possui.Voltando a nosso codigo, vemos que TSpriteFrame possui uma propriedade Rect e que este retangulo define as dimensoes do sprite, mas nao sabe nada sobre sua posicao. Vamos adicionar um novo metodo para resolver isto. TSpriteFrame = class public Rect : TSDL_Rect; TimeSpan : Cardinal; //em milisegundos function GetPositionedRect( position : TPoint ) : TSDL_Rect; inline; end;(...)// retorna o retangulo do sprite transladado (ou transportado) para o ponto "position"function TSpriteFrame.GetPositionedRect(position : TPoint): TSDL_Rect;begin result.x := trunc(position.X); result.y := trunc(position.Y); result.h := self.Rect.h; result.w := self.Rect.w;end;(...)function TGameObject.GetSpriteRect: TSDL_Rect;begin result := fSprite.CurrentFrame.GetPositionedRect( self.Position );end;Agora podemos percorrer uma lista qualquer de objetos e verificar se eles colidem, levando um evento eqivalente. Veja.//assinatura do evento que vamos levantar quando uma colisao for detectadaTGameObjectCollisonEvent = procedure(Sender, Suspect: TGameObject; var StopChecking: boolean) of object;(...)//classe TGameObject atualizada.// note a presenca o evento OnCollided e do metodo CheckCollisions TGameObject = class private function GetSpriteRect: TSDL_Rect; strict protected fRenderer : PSDL_Renderer; fDrawMode : TDrawMode; fOnCollided : TGameObjectCollisonEvent; protected fSprite : TSprite; procedure InitFields; virtual; public Position : TPoint; constructor Create( const aRenderer: PSDL_Renderer ); virtual; destructor Destroy; override; procedure Update(const deltaTime : real ); virtual; abstract; procedure Draw; virtual; abstract; procedure CheckCollisions( Suspects: TGameObjectList); property DrawMode: TDrawMode read fDrawMode write fDrawMode; property Sprite : TSprite read fSprite; property SpriteRect : TSDL_Rect read GetSpriteRect; property OnCollided : TGameObjectCollisonEvent read fOnCollided write fOnCollided; end;(...)//implementacao da checagem de colisoesprocedure TGameObject.CheckCollisions( Suspects: TGameObjectList );var i : integer; myRect : TSDL_Rect; suspectRect : TSDL_Rect; aStopCheckhing : boolean;begin aStopCheckhing := false; myRect := GetSpriteRect; for i:= 0 to Pred( Suspects.Count ) do begin suspectRect := Suspects[i].SpriteRect; if ( SDL_HasIntersection(@myRect, @suspectRect) ) = SDL_TRUE then if Assigned( fOnCollided ) then begin fOnCollided( self, Suspects[i], aStopCheckhing ); if aStopCheckhing then break; end; end;end;CheckCollisions recebe uma lista de objetos "suspeitos" e percorre-os buscando por uma colisao se valendo de HSD_HasIntersection para tal. Se uma colisao for detectada, chamados o evento OnCollided e damos ao callback a chance de parar a com o loop de checagens atraves da variavel aStopCheckhing.Com a rotina de colisao implementada em TGameObject, vamos varrer todos os tiros disparados pelo jogador e verificar se colidem com algum inimigo. Poderiamos testar todas as instancias de TShot contra todas as instancias de TEnemy, mas um controle mais granular e desejavel por uma questao de performance e, principalmente, para mantermos o codigo limpo e facil de acompanhar. Para evitar isto, vamos implementar rotinas de filtro em nossas listas.//retorna uma lista com todos os projeteis que estao seguindo a direcao "aDirection"function TShotList.FilterByDirection(aDireciton: TShotDirection): TShotList;var i: integer; shot : TShot;begin result := TShotList.Create( false ); for i:=0 to Pred(Self.Count) do begin shot := TShot(Self.Items[i]); if (shot.Visible) and (shot.Direction = aDireciton) then result.Add( Self.Items[i] ); end;end;(...)//retorna uma lista com todos inimigos vivos ou todos os mortosfunction TEnemyList.FilterByLife(aAlive: boolean): TEnemyList;var i : integer; enemy : TEnemy;begin result := TEnemyList.Create( false ); for i:=0 to Pred( Self.Count ) do begin enemy := TEnemy(Self.Items[i]); if aAlive then if enemy.HP > 0 then result.Add( enemy ) else if enemy.HP <= 0 then