Foi
no disco Bitmap 2 (há um bocado de tempo atrás)
que mostrei pela primeira vez uma técnica de animação
das mais interessantes e simples de obter. Naquela matéria,
as rotinas foram construídas todas em assembler.
Agora vou mostrar
como chegar ao mesmo resultado usando o Delphi e alguns macetes
da API do Windows.
Repare,
na figura animada, como os elementos se movem com velocidades
diferentes e como cada um interfere com o outro. Tudo isso foi
feito usando a instrução BitBlt, da API.
Fácil e sem mistérios.
A
janela de apresentação das figuras, que usei, possui
as seguintes medidas (todas as medidas são dadas em pixels):
220 de largura por 158 de altura. Essa é a nossa área
de impressão.
Dividimos
nossa imagem em três planos distintos: o primeiro plano
é composto pelas árvores maiores e pelo chão
(elas estão mais próximas do observador; o segundo
plano é formado pelas árvores menores (elas estão
mais longe) e por último as montanhas e as nuvens.
Plano 3
Plano 2
Plano 1
Cada
plano possui um tamanho diferente pois os deslocamentos são
diferentes. Enquanto o terceiro plano, aquele que está
mais longe da visão do observador, desloca um pixel, o
segundo plano desloca dois e o primeiro plano desloca quatro pixels.
Faz sentido, não é mesmo, pois o que está
mais perto do observador se move com mais velocidade do que aquilo
que está mais longe.
Desta
constatação temos que, dada a largura da figura
do terceiro plano, o segundo plano terá o dobro de tamanho
e o primeiro será quatro vezes maior, certo?
Errado,
o raciocínio só vale para a área de deslocamento,
dentro de cada figura. Por exemplo: o terceiro plano possui 325
pixels de largura. A impressão da área de visualização,
partindo da posição zero da figura, cobre os primeiros
220 pixels.
A
última posição "imprimível" será
portanto 325 - 220 = 105. Assim, o terceiro plano se desloca da
posição 0 até a posição 105.
Logo, o segundo plano, que desloca o dobro da distância
do terceiro, precisa de uma figura com no mínimo 105 *
2 + 220 = 430 pixels de largura e o terceiro plano precisa de
um figura com apenas 105 * 4 + 220 = 640 pixels de largura.
Arrá!
640... Hummmm! Não se precipite. Isso foi apenas para facilitar
as coisas e fazer caber a maior figura numa única tela
de 640 x 480. Na verdade, qualquer largura poderia ser usada,
bastando respeitar a regra de relação entre elas.
Se
você ainda não se convenceu, dê uma estudada
na figura a seguir. Ela ilustra o terceiro plano sendo mostrado
na posição mais à direita.
Agora
que já temos as figuras e as medidas, construímos
as suas respectivas máscaras de impressão. Isso
é feito para obtermos o efeito de cor transparente (ou
pode-se usar também uma procedure que já transporte
a imagem levando em consideração a transparência
de uma determinada cor).
Juntando
tudo, nosso sistema está pronto para a programação.
Ah! ia esquecendo: incluí um plano extra, para a composição
do céu.
Ele
nada mais é do que uma figura nas mesmas medidas da área
de visualização e com um degradê azul claro.
Vamos
então à programação, dispensando os
procedimentos burocráticos, tais como criar as TImage,
TSpeedButtom e TScrollBar.
Se
você ainda é "iniciante" em Delphi, basta fazer o
download do arquivo PLANOS.ZIP (no telefone ao lado). Ele
mostra passo a passo o que você deve fazer. De qualquer
forma, já está na hora de aprender a "ler" uma listagem
Delphi.
Usaremos
três constantes integer (Px1, Px2 e Px3)
para definir a posição inicial de impressão
de cada um dos três planos. Elas são inicializadas
com o valor 0 (todo mundo à esquerda).
Construiremos
uma procedure, a qual chamaremos intuitivamente de "MontaPlanos",
que será responsável exatamente por montar e mostrar
os três planos. Nela definiremos 8 variáveis do tipo
handler Bitmap (HBitmap) de acordo com a seguinte tabela:
HPl0
- Plano zero: o céu;
HPl1 - Plano 1;
HPl1m - Máscara do plano 1;
HPl2 - Plano 2;
HPl2m - Máscara do plano 2;
HPl3 - Plano 3;
HPl3m - Máscara do plano 3;
HBuf - Área de visualização;
O primeiro passo
é definir os respectivos handlers:
HBuf:=
Form1.BufTel.Canvas.Handle;
HPl0:= Form1.Pl0.Canvas.Handle;
HPl1:= Form1.Pl1.Canvas.Handle;
HPl1m:= Form1.Pl1m.Canvas.Handle;
HPl2:=
Form1.Pl2.Canvas.Handle;
HPl2m:= Form1.Pl2m.Canvas.Handle;
HPl3:= Form1.Pl3.Canvas.Handle;
HPl3m:= Form1.Pl3m.Canvas.Handle;
Feito
isso, montamos o plano zero (céu) na área de visualização:
Lembra
do parâmetro srccopy? Ele produz uma cópia
sobreposta da imagem fonte, sobre a imagem destino.
A
seguir montamos cada um dos planos:
BitBlt
(HBuf,0,100,220,39, HPl3m,Px3,0, srcand);
BitBlt (HBuf,0,100,220,39, HPl3,Px3,0, srcpaint);
BitBlt (HBuf,0,50,220,87, HPl2m,Px2,0,srcand);
BitBlt (HBuf,0,50,220,87, HPl2,Px2,0,srcpaint);
BitBlt (HBuf,0,0,220,158, HPl1m,Px1,0,srcand);
BitBlt (HBuf,0,0,220,158, HPl1,Px1,0,srcpaint);
Relembrando:
o parâmetro srcand faz com que, na imagem destino,
o que for branco da imagem fonte (no caso a máscara de
impressão) fique como está e o que for preto, na
imagem fonte, fique preto na imagem destino. Digamos
que essa operação "apaga" na imagem destino o que
for preto na máscara.
O
parâmetro srcpaint faz o contrário: mantém
intacto na imagem destino o que for preto na imagem fonte e transfere
tudo aquilo que não for preto. Em termos simples, esta
operação "cola" a imagem fonte, sendo que o preto
fica transparente.
Como
construímos nossa procedure à mão, a imagem
não aparecerá assim, sem mais nem menos. Para vê-la
teremos que informar ao Windows para providenciar uma nova impressão
da área de visualização:
Pronto.
Agora nossa procedure já produz os resultados desejados.
Para finalizar, basta acrescentar à barra deslizante um
pequeno código, no evento onScroll:
Px3:=
SB.Position;
Px2:= SB.Position * 2;
Px1:= SB.Position * 4;
MontaPlanos;
Em
tempo: SB é o nome da barra de deslizamento e Position
o atributo de posição do botão deslizante.
Viu
só como é simples? Mais fácil que isso só
mesmo carregando, no Delphi, o arquivo PLANOS.PDR. Ele
contém todas as imagens, botões e códigos.
Tudo mastigadinho e pronto para as suas próprias experiências.
É só clicar no link abaixo e... Bom
proveito.
|