Sunteți pe pagina 1din 11

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

Site: Url:

GDJ - Grupo de Desenvolvedores de Jogos http://pjmoo.codigolivre.org.br/gdj

Introduo a Programao Orientada a Objetos


Autor : db

Programao Orientada a Objetos

Introduo
A maioria das linguagens de programao modernas oferece suporte para programao orientada a objetos (POO). Essas so baseadas em trs conceitos fundamentais: encapsulamento (normalmente implementado com classes), herana e polimorfismo (ou ligao tardia-late binding). Uma classe um tipo de dado definido pelo usurio, o qual tem alguns dados internos (variveis e propriedades) e alguns mtodos (procedimentos e funes) e normalmente descreve as caractersticas genricas e o comportamento de alguns objetos semelhantes. Um objeto uma instncia de uma classe ou de uma varivel do tipo de dados definido pela classe. Os objetos so entidades reais. Quando o programa executado, os objetos ocupam certa memria para sua representao interna. Voc pode ter quantos objetos precisar de uma classe, levando em conta que os objetos ocupam memria no computador. Veremos adiante como implementar classes e objetos utilizando o Delphi. Para isso vamos desenvolver um aplicativo que permita instnciar vrios objetos de uma mesma classe.

Criando as Classes
Programao Orientada a Objetos

Definindo as classes
A linguagem Object Pascal utilizada pelo Delphi totalmente orientada a objetos. Quando voc cria um novo projeto no Delphi, ele insere no seu projeto um novo form ( TForm1 ). Esse form na verdade herana do TForm, conforme a prpria declarao do Delphi

type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end;

Renomeie o form para frmGame , salve a unit como Game.pas e o projeto como Game_POO.dpr. Jogos de estratgia possuem diversas classes e instncias. Para facilitar a programao podemos desenvolver uma classe "base" para as demais. Vamos criar uma classe padro chamada TVeiculo. Aps a seo Uses do form, declare:

type TVeiculo = class(TObject) Bitmap: TBitmap; PosX, PosY, Speed: Integer; procedure Draw; procedure Move; //Herda funes do TObject //Guarda a imagem do veiculo //Posio e velocidade //Desenha a imagem no plano //Responsvel pela movimentao

procedure LoadBitmap(AFile: string); //Carrega a imagem a partir do HD constructor Create; destructor Destroy; //Responsvel pela construo do objeto //Responsvel pela destruio do objeto

1 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

end;

Pressionando a combinao de teclas Ctrl+Shift+C sobre as procedures o Delphi montara para voc a implementao das mesmas. Digite as implementaes conforme descrito abaixo:

{ TVeiculo } procedure TVeiculo.LoadBitmap(AFile: string); begin //Desenha a Imagem "Bitmap" no Form Bitmap.LoadFromFile(AFile); Bitmap.Transparent := True; end;

procedure TVeiculo.Draw; begin //Desenha a Imagem "Bitmap" no Form frmGame.Canvas.Draw(PosX, PosY, Bitmap); end;

Construtores, como o prprio nome diz so mtodos executados quando o objeto est sendo criado. Nossa classe necessita criar o Bitmap para guardar a imagem. Faremos isso no construtor:

constructor TVeiculo.Create; begin inherited Create; //Chama a herana do TObject Bitmap := TBitmap.Create; //Cria o bitmap end;

A mesma regra se aplica aos Destrutores:

destructor TVeiculo.Destroy;

begin Bitmap.Free; //Destroi o bitmap //Chama a herana do TObject

inherited Destroy; end;

Notem que apareceu a algo novo: Inherited. Esse comando serve para chamar a herana de criao e destruio do objeto TObject, nesse caso estamos reaproveitando essa funo. Voc vai ter mais informaes sobre Herana no prximo captulo desse tutorial.

Herana
Programao Orientada a Objetos

Herana
Uma das principais caractersticas da POO a Herana. Esse conceito facilita o reaproveitamento do cdigo.

2 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

No nosso exemplo, criamos uma classe chamada TVeiculo. Ela serve como base para todos os veculos. Imagine que vamos ter avies, carros e navios. Todos eles sero desenhados no plano, todos vo se mover, todos tero coordenadas X e Y e todos tero uma velocidade. A que est a facilidade... no precisamos reescrever nossas classes do zero, podemos partir da classe TVeiculo. Abaixo da classe TVeiculo declare uma classe TBalloon :

type TBalloon = class(TVeiculo); //TBalloon herda caracteristicas do TVeiculo

Repare na maneira em que a classe TBalloon foi declarada. No existe nenhuma diferena entre a sua antecessora (TVeiculo). TBalloon possui os mtodos Draw, Move, Create e Destroy e as propriedades PosX, PosY, Bitmap e Speed somente pelo fato de ter herdado da classe pai (TVeiculo), mesmo no aparecendo na declarao da mesma. Mas queremos que nosso balo movimente-se com uma caracteristica especial. Portanto devemos re-declarar o mtodo Move, no esquecendo de incluir a palavra chave override que indica que essa classe est sendo reescrevida:

type TBalloon = class(TVeiculo) procedure Move; override; //Re-declaramos o mtodo Move end;

Como o mtodo Move pertence a classe TVeiculo, precisamos "avis-la" que esse mtodo vai ser re-declarado em suas classes "filhas". Para isso utilizamos a palavra-chave Virtual. Repare tambm que o mtodo Move no foi implementado diretamente na classe TVeiculo. Isso porque todos os veiculos do projeto iro se mover, porm cada um de uma maneira diferente. O mtodo move, portanto, deve ser implementado em cada classe "filho". por isso alm de informar que o mtodo Move Virtual, tambm devemos dizer que um mtodo Abstract, ou seja, no ter implementao na classe "pai". A nossa classe TVeiculo ficar assim:

type TVeiculo = class(TObject) Bitmap: TBitmap; PosX, PosY, Speed: Integer; procedure Draw; procedure Move; Virtual; Abstract; //Pode ser redeclarada e no ser implementada na classe "pai" procedure LoadBitmap(AFile: string); constructor Create; destructor Destroy; end;

Pressionando a combinao de teclas Ctrl+Shift+C sobre o mtodo Move da classe TBalloon far com que o Delphi prepare implementao da mesma:

{ TBalloon } procedure TBalloon.Move; begin //Determina o movimento do balo PosY := PosY + Speed; end;

3 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

Alm da classe TBalloon, vamos criar mais uma nova classe, a TZeppelin herdando da TVeculo. Nessa classe, alm de implementar o mtodo Move ( obrigatrio em todas as classes "filhos" ), vamos tambm criar uma nova variavel SpeedFly que indica a velocidade que o Dirigivel ir voar:

type TZeppelin = class(TVeiculo) SpeedFly: Integer; //Nova caracteristica ( exclusiva da classe TZeppelin ) procedure Move; Override; end;

Percebam que o campo SpeedFly pertence somente para a classe TZeppelin. Esse campo no est presente nas classes TVeiculo e TBalloon. Pressione Ctrl+Shift+C e implemente o mtodo move da classe TVeculo:

{ TZeppelin } procedure TZeppelin.Move; begin //Determina o movimento do Dirigivel PosY := PosY + Speed; PosX := PosX + SpeedFly;

if PosX > frmGame.ClientWidth then PosX := 0; end;

Nosso dirigvel desaparece-r no campo direito e dever reaparecer no canto esquerdo da tela. No prximo captulo iremos explicar como proteger e ocultar suas propriedades e mtodos.

Encapsulamento
Programao Orientada a Objetos

Encapsulamento
Existem maneiras de proteger informaes da sua classe. A essa caracterstica da-se o nome de Encapsulamento. Para implementar essa caracterstica, utilizamos as palavras-chave: Private, Protected, Public e Published, onde:
Private: Variveis e mtodos declarados como private somente sero acessados pela prpria classe. Protected: Variveis e mtodos declarados como protected podero ser acessadas por qualquer classe que esteja na mesma Public: Variveis e mtodos declarados como public podero ser acessadas por qualquer classe. Published: Usado na criao de componentes ( mas isso fica para outro tutorial ). Unit .

No nosso exemplo, a varivel Bitmap no pode ser alterada diretamente no programa. Para carregar a imagem deve-se utilizar o mtodo LoadBitmap. Portanto vamos declarar a varivel Bitmap como Private. Nossa classe TVeiculo ficar assim:

type TVeiculo = class(TObject) private

4 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

Bitmap: TBitmap; public PosX, PosY, Speed: Integer; procedure Draw; virtual; //Pode ser redeclarada procedure Move; virtual; Abstract; procedure LoadBitmap(AFile: string); constructor Create; virtual; //Pode ser redeclarada destructor Destroy; virtual; //Pode ser redeclarada end;

Aproveitamos tambm alterar os mtodos Draw, LoadBitmap, Create e Destroy, permitindo ser re-declarada por outras classes. Vamos agora criar uma nova classe chamada TFly:

type TFly = class(TVeiculo) private BitmapInv: TBitmap; public SpeedFly: Integer; procedure Draw; override; procedure Move; override; procedure LoadBitmapInv(AFile: string); constructor Create; override; destructor Destroy; override; end;

Pressionando novamente Ctrl+Shift+C teremos:

{ TFly } procedure TFly.Move; begin //Determina o movimento do avio PosY := PosY + Speed; PosX := PosX + SpeedFly;

if (PosX < 0) or (PosX > frmGame.ClientWidth) then SpeedFly := SpeedFly * -1; end;

procedure TFly.LoadBitmapInv(AFile: string); begin //Carrega a imagem invertida do avio BitmapInv.LoadFromFile(AFile); end;

constructor TFly.Create;

5 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

begin Inherited Create; //Chama a herana na classe TVeiculo BitmapInv := TBitmap.Create; BitmapInv.Transparent := True;

end;

destructor TFly.Destroy; begin BitmapInv.Free; Inherited Destroy; //Chama a herana na classe TVeiculo end;

procedure TFly.Draw; begin if SpeedFly > 0 then inherited Draw //Somente chama a herana se o SpeedFly for maior que "0" else frmGame.Canvas.Draw(PosX, PosY, BitmapInv); end;

Note que no mtodo Draw smente chamamos a herana quando a varivel SpeedFly for maior que "0", caso contrrio desenharemos a imagem invertida na tela. No prximo captulo estaremos estudando como instnciar e controlar nossas classes.

Instnciando
Programao Orientada a Objetos

Instnciando Nossas Classes


Num jogo de estratgia, como Command & Conquer por exemplo, a todo instante estamos construindo novos veiculos e, ao mesmo tempo, mandando eles para batalhas onde acabam sendo destruidos por nossos inimigos. Podemos fazer o mesmo com as classes que criamos. Para tanto coloque em nosso Form 1 Panel, 3 botes e 2 Timers, definindo as propriedades conforme especificado abaixo:

object frmGame: TfrmGame Left = 192 Top = 114 Width = 600 Height = 400 Caption = "Tutorial Sobre Orientao a Objeto" object Panel1: TPanel Height = 40 Align = alTop object btBalao: TButton Left = 4 Top = 5 Width = 80 Height = 30 Caption = "Balo" end

6 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

object btAviao: TButton Left = 88 Top = 5 Width = 80 Height = 30 Caption = "Avio" end object btDirigivel: TButton Left = 172 Top = 5 Width = 80 Height = 30 Caption = "Dirigivel" end end object TimerDraw: TTimer Interval = 50 end object TimerMove: TTimer Interval = 50 end end

Seu form deve ficar como o da figura abaixo:

Poderiamos declarar variveis para as classes, mas se analizarmos bem, nos jogos de estratgia no sabemos quantas instncias ( veiculos ) teremos, o nmero aumenta e diminui durante o jogo. Portanto vamos utilizar um objeto que servir para organizar nossas instnicas. o TList. Declare uma varivel List na clausula var do form:

var frmGame: TfrmGame; List: TList;

No evento OnCreate do Form devemos criar a nossa "lista":

7 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

{ TfrmGame } procedure TfrmGame.FormCreate(Sender: TObject); begin //Cria a lista onde armazenaremos as instncias List := TList.Create;

//Prepara o canvas do form para trabalhar com 2 surfaces DoubleBuffered := True;

//Inicializamos a funo que gera nmeros aleatrios Randomize;

//Determinamos a cor da Fonte Canvas.Font.Color := clWhite;

end;

Alm de criar a lista, tambm avisamos para o form trabalhar com duas surfaces (DoubleBuffered), inicializamos a funo que gera nmeros aleatrios (Randomize) e mudamos a cor da fonte do canvas. No evento OnDestroy do form devemos tambm destruir a lista.

procedure TfrmGame.FormDestroy(Sender: TObject); var i: integer; begin //Destroi as instncias for i := List.Count-1 downto 0 do TVeiculo(List[i]).Free;

//Libera a lista da memria List.Free; end;

Antes de destruir a lista, devemos destruir cada uma das instncias contidas nessa lista. A lista possui uma propriedade Count que indica quantos elementos esto contidos na lista. Fazemos um For para percorrer todos os elementos da lista e destrui-los atravz do mtodo Free. Repare que precisamos fazer um TypeCasting porque a lista no sabe qual classe est guardando... na verdade uma lista guarda ponteiros de memria, ou seja, a lista apenas aponta para o objeto em memria. Devemos fazer referncia ao objeto conforme o exemplo ( TVeiculo(List[ index ] ). Repare que no precisamos saber exatamente se o objeto um avio, dirigivel ou balo. Como todos herdam da classe TVeiculo, basta fazer referncia a ela. Cada vez que clicarmos nos botes, instanciaremos um novo objeto e adicionaremos ele em nossa lista. O cdigo dos botes ficar conforme o exemplo abaixo:

procedure TfrmGame.btBalaoClick(Sender: TObject);

var Balloon: TBalloon;

8 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

begin //criamos o balo Balloon := TBalloon.Create; Balloon.PosX := Random(ClientWidth); Balloon.PosY := 0; Balloon.Speed := Random(3)+1; Balloon.LoadBitmap("balao.bmp");

//Adicionamos o balo na lista List.Add(Balloon);

end;

procedure TfrmGame.btAviaoClick(Sender: TObject); var Fly: TFly; begin //criamos o avio Fly := TFly.Create; Fly.PosX := Random(ClientWidth); Fly.PosY := 0; Fly.Speed := Random(3)+1; Fly.SpeedFly := Random(6)-3; Fly.LoadBitmap("Aviao.bmp"); Fly.LoadBitmapInv("AviaoInv.bmp");

if Fly.SpeedFly = 0 then Fly.SpeedFly := 1;

//Adicionamos o avio na lista List.Add(Fly); end;

procedure TfrmGame.btDirigivelClick(Sender: TObject); var Zeppelin: TZeppelin;

begin //criamos o dirigivel Zeppelin := TZeppelin.Create; Zeppelin.PosX := Random(ClientWidth); Zeppelin.PosY := 0;

9 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

Zeppelin.Speed := Random(3)+1; Zeppelin.SpeedFly := Random(3)+1; Zeppelin.LoadBitmap("Dirigivel.bmp");

//Adicionamos o dirigivel na lista List.Add(Zeppelin); end;

Agora vamos implementar o evento OnTimmer dos dois timmers:

procedure TfrmGame.TimerMoveTimer(Sender: TObject); var i: integer; begin //Timmer responsvel por movimentar todos os objetos da lista for i := List.Count-1 downto 0 do begin TVeiculo(List[i]).Move;

//Quando o objeto sair da tela dever ser destruido e removido da lista if TVeiculo(List[i]).PosY > ClientHeight then begin TVeiculo(List[i]).Free; List.Delete(i); end; end; end;

procedure TfrmGame.TimerDrawTimer(Sender: TObject);

var i: integer; begin //Timmer responsvel por desenhar todos os objetos da lista //Limpo a tela Canvas.Brush.Color := clBlack; Canvas.FillRect(Rect(0,40,ClientWidth,ClientHeight));

//Percorro cada objeto da lista desenhando na tela for i := 0 to List.Count-1 do TVeiculo(List[i]).Draw;

//Escrevo na tela quantos objetos existem Canvas.TextOut(5, 45, "Qtde de Veiculos: "+IntToStr(List.Count)); end;

Utilizamos o mtodo Delete da lista para remover os ponteiros. Executando nosso aplicativo, ficaria conforme a imagem abaixo:

10 de 11

21/02/2012 21:33

GDJ :: Introduo a Programao Orientada a Objetos

http://pjmoo.codigolivre.org.br/gdj/pag_artigo_leitura_impressao.php...

Concluso
Programao Orientada a Objetos

Concluso
Devemos ressaltar que esse tutorial tem como objetivo elucidar aos iniciantes a vantagem de desenvolver games baseados na orientao a objetos, reaproveitando cdigos atravz do uso de heranas... no est em discusso as tcnicas de controle de imagem, etc... Reparem tambm que se precisassemos modificar a maneira com que desenhamos os objetos na tela, no precisariamos mudar nas trs classes, e sim na classe "pai", que a TVeiculo. Alterando qualquer cdigo nessa classe, automaticamente estaria refletindo nas demais. Voc pode obter o fonte atravz do link: Tutorial POO Espero que tenham gostado deste tutorial... sugestes so sempre bem vindas. Meu email : dagmarbezerra@uol.com.br

GDJ 2005 - Colaborao das Comunidades ArsLudica/PDJ (2001/2003)

11 de 11

21/02/2012 21:33

S-ar putea să vă placă și