\n'; document.write(barra); } } changePage();
|
Utilizando Sprites e Bitmaps em Delphi sem DirectXPor Cristiano Kliemann com a colaboração de Giovani Kliemann. Se você quiser fazer qualquer comentário, crítica ou apontar erros, por favor envie um e-mail (veja o link na parte inferior da página). Este pequeno tutorial se destina àqueles que gostariam de fazer animações de bitmaps e sprites (e joguinhos) em Delphi e não têm tempo ou paciência para aprenderem DirectX ou simplesmente não querem usá-lo. O tutorial é composto por uma série de exemplos que demonstram e descrevem dois métodos diferentes de desenho e movimento de sprites. Este texto serve só como introdução aos exemplos. Os exemplos foram escritos em Delphi 5. Para acompanhar o tutorial, você deve pegar os arquivos fonte dos exemplos. Escolha uma das opções: O tutorial foi desenvolvido em e para Delphi 5. Screenshot do exemplo 8:
Screenshot do exemplo 7:
ComentáriosUm problema encontrado pelos programadores quando usam os componentes nativos do Delphi (usando TImage, por exemplo) é que estes não foram desenvolvidos para serem movimentados da forma como os jogos o fazem, mas para ficarem praticamente estáticos no formulário. Ao movimentar um TImage, por exemplo, a imagem pisca ao ser redesenhada na nova posição. Para ver como fica, veja o Exemplo 1. O que acontece para que ocorra este efeito? Quando o Delphi muda a posição de qualquer controle em um formulário, ele informa ao Windows que o retângulo onde estava o bitmap deve ser redesenhado, e que deve ser apagado antes. Ou seja, a imagem pisca porque é apagada antes de ser desenhada na nova posição. A solução, portanto, é óbvia: a área onde está a nova imagem não deve ser apagada antes de desenhá-la. Existem várias formas de fazer isto no Delphi. Serão apresentadas duas soluções através de alguns programas de exemplo. Na realidade, o tutorial constitui-se destes exemplos. Como foi mencionado, este texto serve somente como introdução ao assunto. A primeira solução é a mais simples. Entretanto, é extremamente limitada. Só pode ser usada para mover controles TImage não transparentes. Além disso, somente um TImage pode ser movimentado ao mesmo tempo e, para completar, é lenta. A segunda solução é muito mais interessante. É um pouco mais complicada, mas tem muitas vantagens. Pode-se desenhar sprites (imagens transparentes) de forma muito mais rápida que através do primeiro método. Ela pode também ser usada tranqüilamente para implementar jogos para o Windows usando o Delphi. Claro que, se o assunto é performance, deve-se utilizar DirectX. Jogos de ação, por exemplo, são viáveis só em resolução 320x240 (com 16 bits de cor) ou em computadores com alta performance de vídeo. Nos testes, desenhando 100 imagens de 32x32 pixels e 20 de 64x64 pixels, em resolução 640x480 com 16 bis de cor, num computador K6-2 500MHz com placa Blaster Banshee, chegou a 250 frames por segundo. O mesmo teste, em um K6-2 350MHz com placa on-board SiS 530, não passou de 50 FPS. MétodosOs métodos são demonstrados e descritos nos exemplos que acompanham este tutorial. Os exemplos foram pouco testados. Por isso, não me resposabilizo por qualquer dano causado pelos exemplos. Outra coisa importante: muitos comentários foram retirados de um exemplo para outro. Por isso, caso não souber para que serve algo no código, verifique os exemplos anteriores. Talvez encontre o que quer. Por último, alguns dos exemplos iniciam a demonstração quando você clicar com o mouse no form. Quando uma tela parada for apresentada, clique com o mouse em cima. O primeiro método: usando TImageQuando pensei sobre o problema, imaginei técnicas de uso de back buffers e implementei os exemplos deles. Depois pensei em fazer um exemplo de como era horrível usar o TImage (veja no Exemplo 1). Assim vieram algumas idéias de como fazer com que ele não piscasse e fui testando uma a uma. No fim, cheguei a uma solução muito simples. Como foi mencionado antes, esta técnica se limita a fazer um TImage se movimentar pelo form sem piscar. Além disso, os bitmaps não podem ser transparentes (olhe a propriedade TImage.Transparent). Por isso, se quiser "algo mais", veja a outra técnica. Para saber como este método funciona, você deve abrir o Exemplo 2. Quando um TImage é movido, o Delphi manda invalidar a área dele. Ao fazer isto, indica que é para apagar a área antes. Quem conhece o Windows sabe que uma área inválida só é apagada e redesenhada quando as mensagens são processadas (no Delphi, Application.ProcessMessages). Por isso, antes de executar Application.ProcessMessages, mando validar novamente a área onde a imagem está. Assim, o Windows deixará a área como está, sem apagá-la. Só que assim também não desenhamos nossa nova imagem. Por isso, após processar as mensagens, mando invalidar novamente a área da imagem e mando processar as mensagens novamente. Só que desta vez não mando apagar o fundo antes. O segundo método: back bufferEste método, demonstrados nos exemplos 3, 4, 5, 6, 7 e 8, utiliza um esquema bem conhecido de quem usa o DirectX: o back buffer. Um back buffer é uma porção de memória usada para armazenar a imagem que se deseja desenhar antes de ser transferida para o vídeo. Corresponde a uma imagem geralmente com as mesmas dimensões da área que se deseja desenhar (a área inteira). Em um jogo em tela inteira, por exemplo, corresponde às dimensões do modo de vídeo. Antes de desenhar um quadro (frame), temos que apagar o buffer (pintar da cor que será a cor de fundo), e desenhar a(s) imagem(s) nele. Ao final desta fase, basta transferir todo o buffer para a janela. Como é uma "tela" em memória, não aparece no vídeo e pode ser apagada, desenhada, processada, etc, etc, etc sem que ninguém veja. Quando estiver pronta, basta passar para o vídeo. Além disso, o Delphi nos ajuda bastante ao disponibilizar o objeto TBitmap. Como deve saber, o TBitmap é um objeto que mantém uma imagem e uma palette. A imagem pode ser carregada de arquivos BMP. O próprio TImage utiliza um objeto destes quando sua imagem é carregada de BMP. Um TBitmap pode ser criado sem nenhuma imagem carregada de arquivo. Basta executar o constructor Create e atribuir valores às propriedades Width e Height. É assim que criamos nosso back buffer. Abaixo há explicações simples sobre cada um dos exemplos que demonstram back buffers. As explicações completas estão em comentários nos próprios exemplos. Exemplo 3Este exemplo é o primeiro a utilizar o esquema do back buffer e não implementa ainda transparência. Faz o mesmo que o Exemplo 2 utilizando o back buffer. Exemplo 4É o mesmo que o anterior, só que desenha vários bitmaps ao mesmo tempo, ainda sem transparência. Além disso, os bitmaps são animados (graças ao "donut.bmp" que vem com o DirectX SDK). Exemplo 5O mesmo que o anterior, só que com transparência. É bom mencionar que não é blend. Na transparência, alguns pontos são desenhados e outros não. No blend, você pode determinar o grau de transparência da imagem ou de pontos dela, tornando-a "semitransparente". Exemplo 6Decidi incrementar o anterior incluindo, além dos "donuts", carrinhos (que também foram "generosamente cedidos" pela Microsoft) pulando na tela. Incluí, também, uma estatística no número de frames por segundo e uma maneira de aumentar e diminuir o número de objetos na tela. Obs: mudar o número de objetos só tem efeito se você parar a animação de recomeçá-la. Exemplo 7É a implementação do exemplo anterior com mudança
de modo de vídeo. Você pode escolher o modo que deseja mudando
as constantes CResolWidth e CResolHeight. Exemplo 8Este é o mais interessante. Demonstra um pouco de como fazer um joguinho com as técnicas de utilização de back buffer. Além disso, mostra como usar o teclado sem o DirectX. Use as setas para mover o carrinho (ou nave, se quiser). O código não está comentado adequadamente. Este é um desafio... Boa sorte... |
| Entre em contato: | Modificada em 13.06.2005 |