Artigos, pesquisas, tutoriais e projetos multimídia desenvolvidos em object pascal usando Delphi e Lazarus
Alguns Jogos criados em Delphi
Muita gente, talvez por falta de conhecimento, ou da escassez de títulos comerciais produzidos na ferramenta da CodeGear, duvida da capacidade do Delphi na produção e jogos e simulações de alto desempenho.
É verdade que o C++ impera na indústria, seja nos consoles, nos portáteis, nos celulares (aqui, dividindo o espaço com o Java 2 Mircro Edition, e nos desktops mas, isto se deve muito mais à onipresença de bons compiladores C/C++ nos dispositivos eletrônicos que à (inegável) qualidade técnica da liguagem. Mas, ora! O que o há no C++ que nós não temos em object-pascal? Temos suporte a sobrecarga de operadores, suporte a programação genérica, RTTI, Unicode, integração transparente com Win32 API, DirectX, OpenGL, SDL, acesso dierto ao hardware via inline assembly, compilação para Mac, Linux, GameBoy, XBox (via XNA e crhome) e, finalmente, com a versão 2010, teremos compilação nativa para chips de 64bits!
Todos os jogos dos vídeos foram feitos por hobistas utilizando delphi e/ou free pascal. Alguém ainda duvida?
Animações em tempo real com a VCL - Parte IV
No artigo anterior, criamos uma animação procedural, onde com um algoritmo simples, um padrão de cores foi gerado. Neste artigo vamos criar um efeito sobre uma imagem já existente utilizando um conceito simples de transparência.
Opacidade
Segundo o Wikipedia:A opacidade é uma propriedade óptica da matéria. Um material é considerado opaco quando não permite a passagem da luz em quantidades apreciáveis. Geralmente, diz-se que um material é opaco quando bloqueia a passagem da luz visível. (http://pt.wikipedia.org/wiki/Opacidade)

256
valores possíveis (0..255
) onde 0
define uma imagem completamente transparente e 255
uma imagem completamente opaca.Vamos criar um descendente de TBitmap onde adicionaremos esta propriedade.
TSprite = class(TBitmap) private fOpacity: byte; procedure SetOpacity(const Value: byte); published property Opacity: byte read FOpacity write SetOpacity; end;
Agora vamos instanciar nosso sprite na inicialização do programa (lembrando que estamos modificando o código do template cirado nos artigos anteriores)
procedure TForm1.FormCreate(Sender: TObject); begin ReportMemoryLeaksOnShutdown := True; ClientWidth := 800; ClientHeight := 600; fOffScreen := TBitmap.Create; fOffScreen.PixelFormat := pf24bit; fOffScreen.Width := ClientWidth; fOffScreen.Height := ClientHeight; fOffScreen.Canvas.Font.Color := clGray; fOffScreen.Canvas.Font.Size := 9; sprite := TSprite.Create; sprite.LoadFromFile('img01.bmp'); sprite.Opacity := MAXBYTE div 2; Application.OnIdle := OnIdle; end;
Windows.AlphaBlend
50%
de opacidade sobre um background preto (note que já configuramos opacidade como MAXBYTE div 2
).A primeira coisa que precisamos para usar o Windows.AlphaBlend é configurar um registro do tipo TBlendFunction (Veja a descrição oficial deste struct no MSDN).
procedure TForm1.DrawToBuffer; var Canvas : TCanvas; Blendf : TBlendFunction; begin Canvas := fOffScreen.Canvas; Canvas.Brush.Color := clBlack; Canvas.FillRect(fOffScreen.Canvas.ClipRect); Blendf.BlendOp := AC_SRC_OVER; Blendf.BlendFlags := 0; Blendf.SourceConstantAlpha := sprite.Opacity; Blendf.AlphaFormat := AC_SRC_OVER; end;
O parâmetro
BlendOp
representa a opração de mesclagem a executar. Como queremos copiar nosso sprite “por cima” da imagem de fundo, setamos BlendOP
com a constante AC_SRC_OVER
.O parâmatro
BlendFlags
deve ser sempre zero.SourceConstantAlpha
define um valor de transparência a ser aplicado na imagem de origem. Aqui, simplesmente passamos o valor da opacidade de nosso sprite.Por fim,
AlphaFormat
deve ser AC_SRC_OVER
para que o Windows não tente buscar informações de transparência nos pixels da imagem de origem, aplicando em vez disto, o valor de SourceConstantAlpha
.Pronto. Com nosso
TBlendFunction
configurado, podemos desenhar o sprite semi-transparente. Complemente o método DrawToBuffer
conforme a listagem abaixo e execute o programa para ver o resultado.
procedure TForm1.DrawToBuffer; var Canvas : TCanvas; Blendf : TBlendFunction; begin Canvas := fOffScreen.Canvas; Canvas.Brush.Color := clBlack; Canvas.FillRect(fOffScreen.Canvas.ClipRect); Blendf.BlendOp := AC_SRC_OVER; Blendf.BlendFlags := 0; Blendf.SourceConstantAlpha := sprite.Opacity; Blendf.AlphaFormat := AC_SRC_OVER; Windows.AlphaBlend( Canvas.Handle, {manipulador da imagem de destino} fOffScreen.Width - sprite.Width, {coordenada X} 0, {coordenada Y} sprite.Width, {largura da área de desenho} sprite.Height, {altura da área de desenho} sprite.Canvas.Handle, {manipulador da imagem de origem} 0, {coordenada X} 0, {coordenada Y} sprite.Width, {largura da imagem de origem} sprite.Height, {altura da imagem de origem} Blendf {parâmetros de executação(TBlendFunction)} ); Canvas.TextOut(10, 10, Format('Opacidade : %d', [sprite.Opacity])); end;Se tudo estiver certo, você vai ver uma imagem no canto esquerdo da tela de seu programa. A imagem parece muito escura porque metade a luminosidade foi misturada com o fundo negro. Altere o valor de opacidade do sprite para chegar a resultados diferentes.
Fade In e Fade Out
Uma aplicação muito comum da opacidade em imagens é a criação dos efeitos Fade In e Fade Out. Em um (fade in) uma imagem vai surgindo aos poucos até ficar completamente visível, no outro (fade out) a imagem vai se apagando até sumir completamente. Com o que já temos até aqui, é realmente muito fácil implementar estes efeitos: basta ir alterando o valor da propriedadeOpacity
ao longo do tempo. Vejamos como ficará o método UpdateAnimation.
procedure TForm1.UpdateAnimation; begin if OpIncreasing then sprite.Opacity := sprite.Opacity + 1 else sprite.Opacity := sprite.Opacity - 1; case sprite.Opacity of 0 : OpIncreasing := true; 255 : OpIncreasing := false; end; end;
Execute o programa e veja os efeitos em funcionamento. Para conseguir novos efeitos, altere os valores dos incrementos e decrementos em cada iteração.
Até o próximo post.
Downloads
- FadeIn e FadeOut: Código fonte | executável
Links
Links para as postagens que fazem parte do mini curso "Animações em Tempo real com a VCL"Animações em tempo real com a VCL - Parte III
No artigo anterior, configuramos um formulário padrão da VCL para que pudéssemos exibir animações em sua superfície. Criamos também uma bola, que podíamos manipular pelas setas do teclado e fazê-la se mover pela tela. Nesta parte, vamos falar um pouco de teoria e criar nossa primeira animação procedural.
Um pouco de teoria

Desde o surgimento da animação, o seu fundamento é o mesmo: exibir uma seqüência de imagens estáticas, ligeiramente diferentes entre si, numa a uma velocidade superior a 12 imagens por segundo. Quando isto acontece, o olho envia as imagens paradas ao cérebro, mas este acha que se trata de um objeto animado e une-as, criando os pedaços que faltam para que se tenha a impressão de se estar vendo um objeto animado. Muito embora, não pareça haver um consenso entre os cientistas sobre quantos quadros por segundo são necessários para que a “ilusão da animação” aconteça, 12 quadros parecem ser suficientes para que a maioria dos seres humanos visualize-os como uma animação.
A TV, o cinema, o computador, os desenhos animados e os jogos eletrônicos são todos construídos em cima desta idéia. O sistema PAL-M usado no Brasil usa uma taxa de 30fps (do inglês Frames per Second, literalmente quadros por segundo, é a unidade medida padrão usada na indústria e, portanto iremos utilizá-la de agora em diante), filmes em DVD de boa qualidade usam de 24 a 30fps e, na animação de jogos para computador, uma taxa ideal de 60fps vem se estabelecendo ao longo dos anos.
Quando digo “taxa ideal”, não estou afirmando que é necessário alcançar os 60fps ou que seja errado ultrapassá-los. Na realidade, quanto mais quadros por segundo você puder exibir, mais convincente e suave será sua animação, então, daqui pra frente, vamos escrever nossos programas para que alcancem a maior taxa de fps que conseguirmos.
A composição das cores
Neste formato, utilizado exclusivamente por dispositivos emissores de luz, quando todos os três componentes RGB estão em 0% de sua intensidade obtém-se a cor preta e, no caso inverso, quando todos os três componentes estão em 100%, obtém-se a cor branca. Todas as outras cores são obtidas ao se combinar porções distintas de cada um destes componentes.
Imagens, bitmaps e Pixels
Nos primórdios da computação, quando os monitores eram monocromáticos, as imagens eram simplesmente uma seqüência de bits que dizia se um ponto numa determinada coordenada no monitor deveria estar acesa ou apagada. Um mapa de bits, um bitmap.
O Windows utiliza este conceito para representar tudo o que deve aparecer no monitor. Ele sempre mantém uma imagem do tipo bitmap em uma área especial da memória RAM que o sistema de vídeo usa para montar a imagem final na tela. A este espaço dá-se o nome de frame buffer.
O Delphi, através da classe
TBitmap
, oferece um excelente meio de manipular essas imagens, e o método BitBlit
da API do Windows, nos fornece um modo rápido de copiar imagens para o frame buffer.Um Pouco de Código (finalmente)
Para melhorar um pouco a organização do código escrito no post anterior, vamos criar uma interfaceIDrawable
e fazer com que nosso objeto TBackground
a implemente.IDrawable = interface ['{3E41F055-58F6-4990-9C94-AA29FD4D7CF4}'] function GetVisible: boolean; function GetRect : TRect; procedure SetVisible(const Value: boolean); procedure Draw(Canvas:TCanvas); property Rect: TRect read GetRect; property Visible: boolean read GetVisible write SetVisible; end;A interface é bem intuitiva e dispensa maiores explicações. Ela irá definir o “contrato” para todos os objetos renderizáveis no nosso programa. Agora segue nova definição de
TBackground
adaptado para implementar IDrawable
.TBackgroung = class(TInterfacedObject, IDrawable) private fStep: byte; fSize: uCommon.TSize; fVisible: boolean; function GetVisible: boolean; function GetRect : TRect; procedure SetVisible(const Value: boolean); public constructor Create(pWidth: integer=640; pHeight:integer=480); destructor Free; published {IDrawable} property Rect: TRect read GetRect; property Visible: boolean read GetVisible write SetVisible; {TBackgroung} property Size : uCommon.TSize read fSize; property Step : byte read fStep write fStep; end;Além das propriedades e métodos da interface, criamos duas outras,
Size
e Step
, que irão nos auxiliar no controle da renderização e no controle da animação. Vamos criar uma série de quadros vermelhos que irão mudar de cor de acordo com o valor da propriedade Step. Para isto, vamos implementar o método Draw
.procedure TBackgroung.Draw(Canvas: TCanvas); const SquareW = 40; {largura de cada bloco} SquareH = 40; {altura de cada bloco} SquaresC = 640 div SquareW + 1; {colunas} SquaresR = 480 div SquareH + 1; {linhas} var col, row, i : integer; r : TRect; begin if fVisible then begin for col:=0 to SquaresC-1 do for row :=0 to SquaresR-1 do begin r.Left := Col * SquareW; r.Top := Row * SquareH; r.Right := r.Left + SquareW; r.Bottom := r.Top + SquareH; Canvas.Brush.Color := col * row + Step; Canvas.FillRect(r); end; end; end;
O que fazemos aqui é dividir a tela em linhas e colunas de acordo com as contantes
SquareW
(a largura de cada quadrado) e SquareH
(altura de cada quadrado), atribuir a cada um destas “células” uma cor diferente, que calculamos com base na linha, na coluna e no valor da propriedade Step
para finalmente, desenharmos uma a uma as “células” no Canvas.Só nos resta agora “animar” a cena alterando a propriedade
Step
após cada renderização. Faremos isto no nosso loop principal através do método UpdateAnimation
.procedure TForm1.OnIdle(Sender: TObject; var Done: Boolean); begin ProcessInput; UpdateAnimation; DrawToBuffer; Blit; Done := False; end;
E agora, a implementação de UpdateAnimation.
procedure TForm1.UpdateAnimation; begin BackGnd.Step := BackGnd.Step + 1; end;Pronto! Nosso background animado está concluído. Execute o código para ver o padrão vermelho mudando de tom e experimente brincar com as constantes do método Draw para chegar a outros resultados. Observe que a classe
TBall
também foi alterada para implementar a interface IDrawable
e que uma outra interface (IMoveable
) foi criada para definir os objetos capazes de se mover pela tela.Downloads
Links
Links para as postagens que fazem parte do mini curso "Animações em Tempo real com a VCL"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

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 oOnIdle
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
Links
Links para as postagens que fazem parte do mini curso "Animações em Tempo real com a VCL"Animações em tempo real com a VCL - Parte I

Esta abordagem, porém, não pode ser utilizada para construir uma superfície de desenho adequada para a exibição de animações que exijam uma taxa de atualização aceitável (pelo menos 20 quadros por segundo). Para isso, a solução mais óbvia seria utilizar uma API ou framework projetado especificamente para este fim (como OpenGL ou DirectX).
Existem, porém, dois problemas a ser vencidos para adotar um framework destes. O primeiro problema é que, caso não haja um hardware gráfico moderno disponível na máquina onde a aplicação irá ser executada, nenhuma aceleração de será provida (leia-se: todo o processamento gráfico será feito por software). O segundo problema é a curva de aprendizado, consideravelmente longa, que o programador terá de vencer para conseguir aproveitar os recursos que elas possam oferecer.
Então, qual biblioteca utilizar? Não dá pra fazer isso com a própria VCL?
Sim. Dá sim. Mas algumas otimizações precisam ser feitas. E é sobre estas otimizações que vamos falar.
Double Buffer ou Backbuffer
OTCanvas
representa uma superfície de desenho que pode ser entendida e tratada como um array de pixels ou um buffer de pixels. O Windows mapeia este buffer para a memória de vídeo e então a placa de vídeo trata de interpretar esta informação e convertê-la em uma imagem visível no monitor.Se desenharmos direto num
TCanvas
de um objeto visível, o desenho será imediatamente atualizado na tela. Até aí, tudo bem. Desde que sejam desenhados um ou dois objetos por vez, tudo irá ser atualizado rápido o suficiente para que a transição não seja facilmente percebida.Ponha um
TTimer
num form, configure a propriedade interval
para 20, carregue uma imagem qualquer num TImage
e ponha o seguinte código no evento OnTimer
:procedure TForm1.Timer1Timer(Sender: TObject); begin Canvas.Brush.Color := clWhite; Canvas.FillRect(Canvas.ClipRect); Canvas.Draw(X, Y, Image1.Picture.Graphic); Inc(X); Inc(Y); if X >= ClientWidth - Image1.Width then X := 0; if Y >= ClientHeight - Image1.Height then Y := 0; end;
Ao executar este programa, você verá sua imagem sendo redesenha aproximadamente 50 vezes por segundo (1000/20=50), o suficiente para causar a impressão de movimento, mas a imagem fica piscando constantemente e o resultado é realmente muito feio.
A idéia geral do buffer duplo (Double buffer) é ter uma segunda área de desenho que fique sempre invisível. Daí, em vez de desenhar direto na tela, todos os desenhos seriam gerados neste buffer e, somente depois de pronto, copiaríamos o desenho para a área visível da tela, numa única operação.
A primeira impressão que essa idéia passa é de que, como estaremos percorrendo um caminho maior, as coisas ficarão mais lentas. Mas o fato é que, quando desenhamos num
TCanvas
visível, a operação demora mais porque, além do tempo gasto com o desenho em si, o programa tem que esperar a memória de vídeo ser atualizada para que o as mudanças apareçam na tela e o programa possa seguir. Quando desenhamos na memória (num TCanvas
não visível) este atraso não existe, logo, a operação é concluída muito mais rápido. Além disso, quando vamos exibir a imagem na tela, ela já está pronta e somente uma operação de desenho será realizada nesta “área lenta”, o que contribui para que a animação tenha uma aparência mais agradável.Vejamos como implementar esta idéia em Delphi.
Primeiro, declare uma variável privada do tipo
TBitmap
para ser o nosso “back buffer” e trate a inicialização e destruição deste objeto:private { Private declarations } fOffScreen: TBitmap; (...) procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin FreeAndNil(fOffScreen); end; (...) procedure TForm1.FormCreate(Sender: TObject); begin X := 0; Y := 0; fOffScreen := TBitmap.Create; fOffScreen.PixelFormat := pf24bit; fOffScreen.Width := ClientWidth; fOffScreen.Height := ClientHeight; end;
Agora vamos desenhar na memória e, quando concluído o desenho, vamos transferi-lo para a “área visível” da tela.
procedure TForm1.Timer1Timer(Sender: TObject); begin fOffScreen.Canvas.Brush.Color := clWhite; fOffScreen.Canvas.FillRect(fOffScreen.Canvas.ClipRect); fOffScreen.Canvas.Draw(X, Y, Image1.Picture.Graphic); BitBlt(Canvas.Handle, 0, 0, ClientWidth, ClientHeight, fOffScreen.Canvas.Handle, 0, 0, SRCCOPY); Inc(X); Inc(Y); if X >= ClientWidth - Image1.Width then X := 0; if Y >= ClientHeight - Image1.Height then Y := 0; end;
Execute este programa e veja que o problema da imagem piscando (conhecido como flickering) foi resolvido.
Eliminando interferências do Windows
Outra otimização mais sutil, mas não menos importante, é o tratamento adequado da mensagemWM_ERASEBKGND
que o Windows envia ao programa quando ele acha que alguma área da janela deve ser atualizada.O Delphi, por padrão, em resposta a esta mensagem irá invalidar toda a área cliente da janela, forçando um redesenho completo. Este comportamento faz sentido quando deixamos que o Delphi cuide sozinho do desenho e da atualização da janela, mas no nosso caso, queremos ter controle completo sobre o modo que a janela será exibida.
Vamos criar uma procedure que irá realizar o tratamento desta mensagem. Declare o seguinte procedimento :
procedure WMEraseBg(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND;
E em sua implementação diga ao Windows, que você mesmo irá tratar do redesenho da janela, setando a mensagem
MSG
para 0:procedure TfrmCGScreen.WMEraseBg(var Msg: TWMEraseBkgnd); begin Msg.Result := 0; end;
Um template para animações
Com estas duas otimizações implementadas, já dá pra fazer pequenas animações executarem de maneira eficiente. Mas ainda há espaço para outras otimizações (que trataremos no próximo post), como executar o programa em full screen, substituir oTTimer
por funções mais precisas como QueryPerformaceCounter
e utilizar o evento OnIdle
do TApplication
para realizar os desenhos da animação.Neste link, você pode baixar os fontes de um projeto que implementa todas estas otimizações e utilizá-lo como template para seus próprios projetos. Faça o download do arquivo, abra-o no Delphi, clique com um botão direito em cima do form e escolha a opção “Add to Repository”. Pronto. Este template estará disponível no “Object Repository”!
Para usar o template, clique no menu
File > New > Other,
escolha o formulário adicionado anteriormente, marque a opção “inherit” e sobrescreva o método DrawScene
para criar suas animações.Até o próximo post.
Downloads
- Animação sem buffer: Código fonte | executável
- Animação com buffer: Código fonte | executável
- Template com otimizações: Código fonte
Links
Links para as postagens que fazem parte do mini curso "Animações em Tempo real com a VCL"
Assinar:
Postagens
(
Atom
)