{=========================================================}
{Início da listagem
1) Ajuste as propriedades do Form1 p/ os seguintes valores:
Caption: TanKiller
ClientHeight: 348
ClientWidth: 536
Height: 375
Width: 544
As demais propriedades ficam como estão. Esta regra serve
para os demais componentes.
2) Crie um TPanel (Standard) com as seguintes propriedades:
BevelOuter: bvLowered
Caption: ''
Color: clBlack
Height: 256
Left: 5
Top: 5
Width: 526
3) Crie uma TImage (Additional), dentro do Panel1, com as
seguintes propriedades:
Align: alClient
Cursor: crCross
Picture: (carregue a imagem Tank01.bmp)
Esta TImage será nossa tela, onde iremos montar as demais
figuras e elementos gráficos do jogo. O acesso à tela será
feito pela API BitBlt, usando um handle apropriado.
4) Crie uma TImage (Additional), fora do Panel1, com as
seguintes propriedades:
Height: 64
Left: 145
Name: Image2
Top: 275
Visible: False
Width: 128
5) Crie uma TImage (Additional), fora do Panel1, com as
seguintes propriedades:
AutoSize: True
Height: 100
Left: 400
Name: Image3
Picture: (carregue a imagem Tank02.bmp)
Top: 245
Visible: False
Width: 131
Esta TImage contém o padrão que será usado para montar o
chão da tela. Serão quatro repetições e ele será montado
pela procedure que limpará a tela.
6) Crie uma TImage (Additional), fora do Panel1, com as
seguintes propriedades:
AutoSize: True
Height: 32
Left: 10
Name: Image6
Picture: (carregue a imagem Tank03.bmp)
Top: 305
Visible: False
Width: 128
Esta é a matriz do tanque 0 Km. Agora podemos fazer o
tanque andar de um lado para outro da tela.
7) Crie um TTimer (System):
Interval: 60
Name: Timer1
8) Crie um TSpeedButton:
Caption: Iniciar
Height: 25
Left: 15
Top: 270
Width: 76
9) Crie as seguintes variáveis globais:
implementation
{$R *.DFM}
{
const
Stat: byte = 0; //Liga/desliga animação
Tiro: byte = 0; //Tiro em andamento
var
Buf: TBitmap; // Buffer de tela
Tx,Ty,Cx,Vt: integer;
Tanques,Destrd,Ammo,Explod: integer;
10) Crie o evento OnClick, no SpeedButten1. Este botão irá
inicializar uma partida. A seguir digite as seguintes
linhas de programação, dentro da procedure:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Stat:= 2;
Tanques:= 0; Destrd:= 0; Ammo:= 15;
end;
11) Antes de movimentar o tanque, vamos criar a procedure
que limpa a tela e a inicialização do programa:
procedure LimpaBuf;
var
Chao,HBuf: HBitmap;
begin
HBuf:= Buf.Canvas.Handle;
Chao:= Form1.Image3.Canvas.Handle;
Buf.Canvas.Brush.Color:= clBlack;
Buf.Canvas.Pen.Color:= clBlack;
Buf.Canvas.Rectangle(0,0,524,154);
BitBlt(HBuf,0,154,131,100,Chao,0,0,SRCCOPY);
BitBlt(HBuf,131,154,131,100,Chao,0,0,SRCCOPY);
BitBlt(HBuf,262,154,131,100,Chao,0,0,SRCCOPY);
BitBlt(HBuf,393,154,131,100,Chao,0,0,SRCCOPY);
end;
12) Crie o evento OnActivate, no Form1 (ajusta os parâm.ts
inciais de funcionamento e cria o buffer de tela):
procedure TForm1.FormActivate(Sender: TObject);
begin
Buf:= TBitmap.Create; //Cria o buffer de tela
Buf.Width:= Image1.Width; //Largura
Buf.Height:= Image1.Height; //Altura
Buf.Canvas.Font.Color:= clLime; //Parâmetros para a
Buf.Canvas.Font.Name:= 'arial'; //impressão dos números
Buf.Canvas.Font.Style:= [fsBold];
Buf.Canvas.Font.Height:= 32;
end;
13) Crie o evento OnTimer, no Timer1 e coloque a seguinte
programação nele:
procedure TForm1.Timer1Timer(Sender: TObject);
var
Fogo,HBuf,Tela,Tank,Matrz,Cano,Boom: HBitmap;
ACan,Tmb,Mosca: integer;
Num: string;
begin
//Define os handles das imagens
HBuf:= Buf.Canvas.Handle;
Tela:= Image1.Canvas.Handle;
Tank:= Image2.Canvas.Handle;
//Pt 01:
//Se tiver um tanque andando...
if Stat = 1 then begin
//Apaga todo o buffer de tela
LimpaBuf;
//Transfere o tanque para o buffer
BitBlt(HBuf,Tx,Ty,128,64,Tank,0,0,SRCCOPY);
//Pt02
//Anda com o tanque dois pixels
inc(Tx,2);
//Se o tanque saiu da tela, recomeça com outro tanque
if Tx > 530 then Stat:= 2;
//Pt5
//Transfere o buffer para a tela
BitBlt(Tela,0,0,524,254,HBuf,0,0,SRCCOPY);
Image1.Repaint;
end;
//Vai ser lançado um tanque novo
if Stat = 2 then begin
//Apaga o buffer do tanque
Image2.Canvas.Brush.Color:= clBlack;
Image2.Canvas.Pen.Color:= clBlack;
Image2.Canvas.Rectangle(0,0,128,64);
//Transfere a imagem de um tanque intacto para o buffer
Matrz:= Image6.Canvas.Handle;
BitBlt(Tank,0,32,128,32,Matrz,0,0,SRCCOPY);
//Ajusta demais parâmetros
Tx:= -128; Ty:= 90; Explod:= 0;
inc(Tanques); Stat:= 1;
end;
end;
Até aqui, ao compilar, o tanque será montado no buffer de
tela e irá andar da esquerda para a direita. Agora vamos
montar a arma do jogador e seus controles.
14) Crie uma TImage com as seguintes propriedades (cano da
arma):
AutoSize: True
Height: 32
Left: 310
Name: Image4
Picture: (carregue a imagem Tank04.bmp)
Top: 305
Visible: False
Width: 48
15) Crie uma TImage com as seguintes propriedades (fogo que
sai do cano da arma):
AutoSize: True
Height: 13
Left: 315
Name: Image5
Picture: (carregue a imagem Tank05.bmp)
Top: 290
Visible: False
Width: 20
16) Crie um TScrollBar com as seguintes propriedades (será o
sistema de deslocamento do cano da arma):
Height: 11
LargeChange: 10
Left: 185
Max: 500
Min: 0
Position: 245
SmallChange: 10
Top: 270
Width: 156
17) Complemente o evento OnTimer com os seguintes códigos
(nos seus respectivos locais assinalados - Pt ??):
//Pt 01:
Cano:= Image4.Canvas.Handle;
Fogo:= Image5.Canvas.Handle;
...
...
//Pt 02:
//Verifica se a arma recuou (foi dado um tiro)
if Tiro = 220 then Acan:= 230 else Acan:= 222;
//Transfere a figura do cano da arma (c/máscara)
BitBlt(HBuf,ScrollBar1.Position,Acan,24,32,
Cano,24,0,SRCAND);
BitBlt(HBuf,ScrollBar1.Position,Acan,24,32,
Cano,0,0,SRCPAINT);
//Pt03
Compile o que foi digitado até aqui e verifique se o cano da
arma está se deslocando pela tela como é esperado.
18) Agora vamos montar o botão que dispara os tiros. Crie
um TSpeedButton com as seguintes propriedades:
Caption: DISPARAR
Height: 36
Left: 230
Top: 290
Width: 71
19) Crie o evento OnClick para este botão, com os seguintes
códigos de programação:
procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
//Se não tem um tiro em andamento...
if Tiro = 0 then begin
//Se tem munição para atirar...
if Ammo <> 0 then begin
//Cx = distância do tiro à esquerda
Cx:= ScrollBar1.Position+11;
//Fator de deslocamento da bala
Vt:= 32;
//Menos um tiro
dec(Ammo);
//Lá vai bala...
Tiro:= 220;
end;
end;
end;
20) Complemente o evento OnTimer com os seguintes códigos
(nos seus respectivos locais assinalados - Pt ??):
//Pt03:
//Se tiver um tiro em andamento...
if Tiro > 0 then begin
//Define o comprimento da bala (1/2 pixels)
if Tiro < 155 then Tmb:= 1 else Tmb:= 2;
//Transfere a bala para o buffer
BitBlt(HBuf,Cx,Tiro,1,Tmb,Cano,24,0,SRCCOPY);
//Se o tiro foi dado agora, fogo na boca da arma
if Tiro = 220 then begin
//Transfere o fogo
BitBlt(HBuf,Cx-4,216,10,13,Fogo,20,0,SRCAND);
BitBlt(HBuf,Cx-4,216,10,13,Fogo,0,0,SRCPAINT);
end;
//Ajusta o próximo deslocamento do tiro
dec(Tiro,Vt); Vt:= ((Vt + 2) div 2) + 1;
//Se o tiro chegou no nível do alvo...
if Tiro < 140 then begin
//Calcula distância da margem esquerda do tanque
Tiro:= 0; Mosca:= Cx-Tx;
//Se acertou no tanque...
if (Mosca < 120) and (Mosca > 10) then begin
//Marca o tanque com o furo
BitBlt(Tank,Mosca,51,2,2,Cano,20,0,SRCCOPY);
//Se acertou na área da frente, grito do homem
//if (Mosca > 95) and (Mosca < 99) then...
//Se acertou no meio do tanque, grito do whookie
//if (Mosca > 75) and (Mosca < 79) then...
//Se acertou na trazeira (painel de munição)
if (Mosca > 45) and (Mosca < 48) and (Explod = 0)
then begin
//Explode o tanque
Explod:= 1; inc(Destrd); inc(Ammo,5);
end;
end;
end;
end;
ATENÇÃO: como a montagem do som envolve o uso do DGC e do
Direct-X, não vamos detalhá-lha aqui. Mas indicaremos onde
os efeitos sonoros ocorrem na versão original. Se quiser
mais detalhes sobre os sons, depois de montada a versão
passo-a-passo, recorra à versão completa do jogo.
Compile como está e veja os resultados. O tanque anda de
um lado para outro, o canhão se desloca de acordo com a
posição da ScrollBar e a bala, depois de disparada, segue
a trajetória em direção ao alvo.
21) A explosão do tanque, quando a bala acerta 1 determinado
ponto, é feita no próprio evento OnTimer1. Basta
complementar o Pt4:
//Pt4
//Se tem uma explosão em andamento...
if (Explod > 0) and (Explod < 8) then begin
Boom:= Image7.Canvas.Handle;
//Transfere o frame da explosão para o tanque
BitBlt(Tank,0,0,128,50,Boom,0,(Explod-1)*50,SRCCOPY);
inc(Explod);
end;
22) Crie uma TImage com as seguintes propriedades (explosão
do tanque):
AutoSize: True
Height: 350
Left: 385
Name: Image7
Picture: (carregue a imagem Tank06.bmp)
Top: -5
Visible: False
Width: 128
23) Finalmente, informa ao jogador quantos tiros ainda lhe
restam, quantos tanques passaram e quantos ele acertou.
Basta acrescentar o trecho a seguir no Pt5, do evento
OnTimer1:
//Pt5
//Imprime quantidade de tiros que ainda tem
Buf.Canvas.Font.Color:= clLime;
Num:= '00' + IntToStr(Ammo);
Num:= copy(Num,length(Num)-2,3);
Buf.Canvas.TextOut(5,0,Num);
//Imprime quantos tanques já passaram
Num:= '0' + IntToStr(Tanques);
Num:= copy(Num,length(Num)-1,2);
Buf.Canvas.TextOut(430,0,Num);
//Imprime quantos tanques foram destruídos
Buf.Canvas.Font.Color:= clRed;
Num:= '0' + IntToStr(Destrd);
Num:= copy(Num,length(Num)-1,2);
Buf.Canvas.TextOut(480,0,Num);
Compile e divirta-se com o TanKiller.
|