Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Animações em tempo real com a VCL - Parte II

No post anterior, fizemos uma introdução ao conceito de “Double buffer” e realizamos o tratamento da mensagem WM_ERASEBKGND para ajudar a otimizar um formulário VCL com o intuito de exibir animações de qualidade nele. Neste post, iremos finalizar estas otimizações.

Usando o evento OnIdle

O objeto Application está presente em todos os programas GUI do Delphi e é utilizado para simplificar a interação com a API do Windows. De fato, o objeto Application encapsula todas as chamadas à API necessárias para inicializar, registrar e manipular janelas, além de publicar alguns eventos globais.

O evento TApplication.OnIdle é um desses eventos. Ele é disparado sempre que o programa fica ocioso, ou seja, sempre que não houver mais nenhuma instrução a ser executada, o evento OnIdle será chamado. Isso o torna especialmente útil quando queremos realizar uma tarefa em segundo plano sem utilizar threads, ou quando queremos que uma determinada função seja executada repetidamente sem afetar o desempenho do programa.

Dois passos são necessários para utilizarmos o evento OnIdle.

Primeiro declare um procedimento privado em seu formulário e implemente-o como o código a seguir:

procedure OnIdle(Sender: TObject; var Done: Boolean);
begin
Done := false;
end;

Note que não importa o nome do que você der ao método. O que importa é que a lista de parâmetros seja idêntica à do exemplo para que a assinatura do método seja compatível com a definição do evento Application.OnIdle para que, dessa forma, possamos associar nosso método ao evento.

Para finalizar, ponha o trecho de código abaixo no OnCreate do formulário e estaremos prontos para realizar nosso processamento neste evento.

procedure TfrmCGScreen.FormCreate(Sender: TObject);
begin
Application.OnIdle := OnIdle;
end;

O loop principal (main loop)

Iremos utilizar o OnIdle para nosso loop principal.

O loop principal de uma aplicação de computação gráfica pode assumir várias formas, mas todas elas implementam variações da mesma lógica:

1. INICIO
2. ENQUANTO(ESTADO <> SAIR)
2.1. PROCESSA OS COMANDOS DO USUÁRIO;
2.2. ATUALIZA DO ESTADO DA ANIMAÇÃO;
2.3. DESENHA A CENA NO BUFFER;
2.4. EXIBE A CENA NO MONITOR;
3. FIM;

Vamos criar então os métodos equivalentes. Declare na seção privada do formulário os métodos a seguir e pressione Ctl + Shit + C para que o Delphi crie a implementação de todos:


procedure ProcessInput;    {passo 2.1}
procedure UpdateAnimation; {passo 2.2}
procedure DrawToBuffer; {2.3}
procedure Blit; {2.4}

Agora implemente o método OnIdle para que a estrutura do nosso algoritmo fique completa.

procedure TForm1.OnIdle(Sender: TObject; var Done: Boolean);
begin
ProcessInput;
UpdateAnimation;
DrawToBuffer;
Blit;
end;

Se você compilar e executar o programa agora, você verá uma janela do Windows vazia. Nada muito empolgante até agora: temos a estrutura geral pronta, mas nada pra exibir.

Vamos criar um objeto to TBall (adicione o arquivo uBall.pas ao seu projeto) no centro da tela. Declare uma variável pública chamada Ball e modifique o evento OnCreate do formulário para:

procedure TForm1.FormCreate(Sender: TObject);
begin
ReportMemoryLeaksOnShutdown := True;

{teremos uma tela de 800 x 600 pixels}
ClientWidth := 800;
ClientHeight := 600;

{Criamos nosso bitmap de buffer}
fOffScreen := TBitmap.Create;

{iremos trabalhar com cores de 24bit}
fOffScreen.PixelFormat := pf24bit;

{configura as dimensões do buffer de acordo com as dimensões do formulário}
fOffScreen.Width := ClientWidth;
fOffScreen.Height := ClientHeight;
Ball := TBall.Create;
Ball.Position:= Point(ClientWidth div 2, ClientHeight div 2);
Ball.Color := clWhite;
Ball.Diameter := 30;
Application.OnIdle := OnIdle;
end;

Agora é preciso exibir o objeto. Vamos implementar os métodos DrawToBuffer e Blit:

procedure TForm1.DrawToBuffer;
var
Canvas : TCanvas;
begin
Canvas := fOffScreen.Canvas;

{Primeiro, limpamos o buffer com um fundo preto...}
Canvas.Brush.Color := clBlack;

{Agora desenhamos a bola}
Canvas.FillRect(fOffScreen.Canvas.ClipRect);
Ball.Draw(Canvas);
end;

procedure TForm1.Blit;
begin
BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientHeight,
fOffScreen.Canvas.Handle, 0, 0, SRCCOPY);
end;

Com isto temos, finalmente, nosso framework funcionando. Tudo bem que ele não faz mais nada além de desenhar uma bola no meio da tela, mas o “trabalho sujo” de configuração do ambiente foi realizado.
Para finalizar este post, vamos movimentar um pouco a bola pela tela usando as setas do teclado.

Implemente o método ProccessInput usando a função GetKeyState como na listagem abaixo. Note que os botões + e - irão manipular a velocidade em que a bola se movimenta.

procedure TForm1.ProcessInput;
begin
if GetKeyState(VK_UP) then
Ball.Move(0,-1);

if GetKeyState(VK_DOWN) then
Ball.Move(0, 1);

if GetKeyState(VK_LEFT) then
Ball.Move(-1, 0);

if GetKeyState(VK_RIGHT) then
Ball.Move(1, 0);

if GetKeyState(VK_SUBTRACT) then
Ball.Speed := Ball.Speed - 0.1;

if GetKeyState(VK_ADD) then
Ball.Speed := Ball.Speed + 0.1;
end;

Compile o projeto e experimente um pouco. Note que a bola não ultrapassa os limites da tela e que a classe TBall é responsável por este tratamento.

No próximo post, iremos adicionar um fundo com animação iremos expandir a classe TBall para trabalhar com sprites animados.

Até o próximo post.

Downloads

  • Código fonte | Executável

    Links

    Links para as postagens que fazem parte do mini curso "Animações em Tempo real com a VCL"
    • Parte I
    • Parte II
    • Parte III
    • Parte IV


    This post first appeared on Computação Gráfica E Jogos Em Pascal, please read the originial post: here

    Share the post

    Animações em tempo real com a VCL - Parte II

    ×

    Subscribe to Computação Gráfica E Jogos Em Pascal

    Get updates delivered right to your inbox!

    Thank you for your subscription

    ×