Você está na página 1de 40

5. JOGOS 2D Nesse bloco vamos estudar os fundamentos de aplicaes e jogos 2D.

Iniciaremos explicando como configurar a janela para exibio de grficos 2D e iremos at tcnicas avanadas como parallax scrolling. Por que devemos estudar jogos 2D? - So o tipo mais jogado, pois a maioria da pessoas preferem jogos casuais. - Eles rodam em maquina de baixo desempenho, por isso possuem um mercado maior. - Vivemos uma febre de celulares e por enquanto eles s rodam jogos 2d. PRIMITIVAS Vamos fazer um breve estudo sobre os elementos mais bsicos da programao 2D: a definio do modo grfico e as primitivas grficas. Primitivas so recursos internos do Blitz3D com os quais podemos compor imagens sem a necessidade de importar arquivos criados em outras ferramentas. Definindo o modo grfico A primeira coisa a se fazer ao iniciar uma aplicao com grficos 2D dizer ao computador como desejamos que esses grficos sejam exibidos. Podemos fazer isso com o comando Graphics. Veja a assinatura do comando:
Graphics resoluo x, resoluo y, paleta, modo

Aumente as laterais, depois a altura e teste maximizar, restaurar e minimizar. Exemplo 4


Graphics 640, 480, 16, 3 Oval 270,190, 100,100,1 WaitKey

Ttulos nas Janelas Caso voc faa a opo por rodar um aplicativo em modo de janela provavelmente vai querer colocar o ttulo do jogo na janela. Isso pode ser feito com o comando AppTitle. Exemplo 5
Graphics 640, 480, 16, 2 AppTitle ":-) 2D" WaitKey

Exemplo 1
Graphics 640, 480, 16, 1 Oval 270,190, 100,100,1 WaitKey

No exemplo acima estamos configurando a resoluo da tela em 640, 480. Definimos a paleta de cores para 16 bits e definimos que o programa deve rodar em modo fullscreen, isso , tela cheia "1". Veja o mesmo programa com outra resoluo de tela. Exemplo 2
Graphics 800, 600, 16, 1 Oval 270,190, 100,100,1 WaitKey

Duplo Buffer A tcnica de Double Buffer consiste em dividir o esforo de composio da imagem do esforo para a exibio da mesma. Quando a composio da imagem se d diretamente no Buffer de vdeo comum gerar fantasmas na imagem, aquelas falhas que as deixam meio transparentes. Isso se d porque acabamos vendo o processo de composio da tela. Com o uso de Double Buffer a imagem composta em outra rea e s colocada na tela quando ela estiver pronta. Para usar essa tcnica no Blitz3D precisamos usar dois comando: Backbuffer() e Flip. Com o primeiro comando definimos o modo de buffer para dois buffers. Caso estejamos usando o modo de double buffer deveremos usar o comando Flip para colocar a imagem do Buffer de Composio no Buffer de Vdeo. A falta desse comando pode gerar o inconveniente de as imagens simplesmente no serem exibidas. Exemplo 6
Graphics 640, 480, 16, 2 SetBuffer BackBuffer() Oval 270, 190, 100, 100, 1 Flip WaitKey

O prximo exemplo mostra uma adaptao do exemplo anterior, agora rodando em modo de janela. Exemplo 3
Graphics 640, 480, 16, 2 Oval 270,190, 100,100,1 WaitKey

Desenhando um ponto A primeira primitiva grfica que iremos estudar o comando Plot. Ele desenha um ponto na tela, que tem exatamente o tamanho de um pixel. Para ser executado ele deve receber as coordenadas x e y de onde ele dever ser exibido. Exemplo 7
Graphics 400, 300 Plot 200, 150 WaitKey Como o Plot exibe um

Uma opo pelo modo 3 far com que voc possua uma janela redimensionvel. Rode o exemplo abaixo e teste essa possibilidade.

ponto do tamanho de um pixel, podemos usar vrios deles para

criar grficos ou formas geomtricas mais complexas. Mas no recomendvel fazer uso excessivo desse tipo de recurso, pois esses comandos de primitivas so um pouco lentos. No exemplo abaixo usamos laos For-Next para preencher a tela com Plot. Veja que isso demanda um esforo excessivo. Exemplo 8
Graphics 800, 600 While Not KeyHit(1) Color Rnd(255), Rnd(255), Rnd(255) For y = 1 To 600 For x = 1 To 800 Plot x, y-recuo Next Next Wend

color J usamos algumas vezes esse comando em programas anteriores como no exemplo que voc acabou de ver. Esse comando e responsvel por mudar a cor da paleta de desenho. a cor da paleta de desenho que determina qual ser a cor de textos e primitivas grficas. Esse comando funciona por meio de trs argumentos: a saturao de cor Red (vermelha); a saturao de cor Green (verde) e a saturao de cor Blue (azul). As iniciais dessas cores correspondem ao padro de cores RGB Red, Green e Blue. Por meio desse sistema de cores podemos construir qualquer cor pela mistura dessas trs cores primitivas. O programa abaixo demonstra como so compostas as cores Exemplo 9
Graphics 800, 600, 16,1 SetBuffer BackBuffer() R = 255 G = 255 B = 255 While Not KeyHit(1) Cls Color 255, 255, 255 Text 50, 50, "** BOTOES DIREITO E ESQUERDO
DO MOUSE GRADUAM AS CORES **"

Rect 240, 430 - B, 70, 25 Text 265, 470, B mx = MouseX() my = MouseY() Color 255,0,255 Text mx-5, my-5, "+" If (mx > 40) And (mx < 110) If (my > (430 - R)) And (my < 455 - R) If MouseDown(1) And (R < 255) Then R = + 5 If MouseDown(2) And (R > 0) Then R = R 5 EndIf EndIf If (mx > 140) And (mx < 210) If (my > (430 - G)) And (my < 455 - G) If MouseDown(1) And (G < 255) Then G = + 5 If MouseDown(2) And (G > 0) Then G = G 5 EndIf EndIf If (mx > 240) And (mx < 310) If (my > (430 - B)) And (my < 455 - B) If MouseDown(1) And (B < 255) Then B = + 5 If MouseDown(2) And (B > 0) Then B = B 5 EndIf EndIf GetMouse() Flip Wend

R -

G -

B -

Color R, G, B Oval 400, 190, 300, 300, 1 Color 255,0,0 Rect 50,200, 50, 255 Color 0,255,0 Rect 150,200, 50, 255 Color 0,0,255 Rect 250,200, 50, 255 Color 100,100,100 Rect 40, 430 - R, 70, 25 Text 65, 470, R Rect 140, 430 - G, 70, 25 Text 165, 470, G

Programinha interessante... Entendeu Tudo? Acredito que tudo que est nele j foi discutido. Talvez voc se confunda um pouco com a lgica do programa que est um pouco abstrata, mas o importante aqui voc saber como se controla a paleta de cores por meio do comando Color e ter uma ferramenta para descobrir como compor uma cor desejada. Desenhando linhas Podemos desenhar linhas no Blitz3D por meio do comando Line. Para que ele funcione devemos declarar as posies x e y de onde a linha comea e declarar a posies x e y de onde ela deve terminar. Assim, a lgica desse comando Line x1,y1,x2,y2. Veja um exemplo prtico. Exemplo 10
Graphics 800, 600 Line 100,100, 700, 500 WaitKey

Desenhando retngulos Para desenhar retngulos devemos passar 5 argumentos para o comando Rect. A posio x e posio y onde ele ser desenhado; largura; altura e se ser preenchido ou vazado.

O exemplo a seguir cria a retngulo na posio x = 100 e y =100 na tela de dimenses 100 x 50, vazado, pois seu ultimo argumento 0. Exemplo 11
Graphics 800, 600 Rect 100, 100, 100, 50, 0 WaitKey

Perceba que colocamos o som em uma varivel meusom para podermos manipul-lo depois. O normal que, em um jogo, exista uma pasta s para mdias. O comando abaixo carrega o som a partir de uma pasta mdia dentro da nossa pasta do projeto, onde fica o cdigo fonte.
meusom = LoadSound(mdia\tiro.wav)

Para criar retngulos preenchidos devemos usar o valor 1. Exemplo 12


Graphics 800, 600 Rect 100, 100, 100, 50, 1 WaitKey

Desenhando crculos e ovais Para desenhar circunferncias usamos o comando Oval. Ele tem a mesma assinatura do comando de desenho de retngulos. Veja um exemplo onde desenhamos uma oval vazada. Exemplo 13
Graphics 800, 600 Oval 200, 200, 100, 50, 0 WaitKey

Veja que fizemos isso por meio de endereamento relativo, isso , no demos a localizao a partir da raiz, do disco rgido, mas a partir da pasta do arquivo principal, isso , relativo ao arquivo principal. Em tempo de projeto o arquivo principal o cdigo fonte e depois de compilado, o arquivo principal o seu executvel. Veja abaixo um exemplo de endereamento absoluto, isso , a partir da raiz.
meusom = LoadSound(c:\jogo\mdia\tiro.wav)

Nesse prximo exemplo desenhamos um crculo preenchido. Exemplo 14


Graphics 800, 600 Oval 200, 200, 100, 100, 1 WaitKey

Veja que esse tipo de endereamento desaconselhado, pois se voc mudar o local da pasta do jogo, ele no vai funcionar mais. Para executar um som usamos o comando PlaySound e damos como parmetro para esse comando a varivel na qual carregamos o som.
PlaySound meusom

Sons O que seria de um jogo sem os efeitos sonoros... O Blitz3D possui comandos especficos para sons, musicas e som 3d. Os formatos suportados originalmente so: raw, wav, mp3 e ogg; mas isso no impede que voc faa uso de uma Dll far ampliar para outros tipos de sons. Como estamos tratando aqui de jogos 2d, vamos abordar nesse primeiro momento especificamente efeitos sonoros para esse tipo de jogo. Quando chegarmos na parte de jogos 3d, ns explicaremos o funcionamento de som 3d. Carregando e executando um som Para carregar um som para a memria usamos o comando LoadSound e passamos como referncia a esse comando o nome do arquivo e, se ele estiver em uma pasta diferente de onde est o seu cdigo executvel, voc tambm precisar indicar o local onde ele est. Por exemplo, se o arquivo de som ficar na mesma pasta do seu executvel e do seu cdigo fonte, podemos carregar um arquivo de som chamado tiro.wav assim:
meusom = LoadSound(tiro.wav)

O som ser executado apenas uma vez, do seu incio at o seu fim. Se ele tiver um segundo de durao ento ele executar por esse tempo e ir parar. Vamos a um exemplo prtico sobre sons. Veja que colocamos nosso som dentro de uma pasta de mdia. Exemplo 15
meusom = LoadSound("midia\tiro.wav") PlaySound meusom WaitKey

Tocar um som em loop Se desejarmos, podemos tocar o som em loop. Para isso devemos configurar o som para ser executado dessa forma por meio do comando LoopSound. Veja que esse comando aplicado varivel do som e no no comando de play. Exemplo 16
meusom = LoadSound("midia\sapo.wav") LoopSound meusom PlaySound meusom WaitKey

Parar a execuo Para ter um controle maior sobre as propriedades do som como, por exemplo, para a execuo deles, devemos selecionar os canais de som. Para selecionar o canal de som, basta pegar esse canal em uma

varivel quando mandamos o som ser executado.


meucanal = PlaySound(meusom) Da podemos usar o comando StopChannel

sobre o canal de som para parar sua execuo.


StopChannel meucanal

fase que est sendo jogada na memria e no sobrecarregamos o sistema. Como carregar um som voc j sabe, s dar o comando LoadSound. Para descarregar um som da memria usamos o comando
FreeSound.

Exemplo19
meusom = LoadSound("midia\sapo.wav") LoopSound meusom PlaySound meusom While Not KeyHit(1) Text 50,10, "Tecle Space para Descarregar o Som" If KeyHit(57) FreeSound meusom EndIf Flip Wend

Vamos a um exemplo executvel Exemplo 17


meusom = LoadSound("midia\sapo.wav") LoopSound meusom meucanal = PlaySound (meusom) paralisa() StopChannel meucanal paralisa() meucanal = PlaySound (meusom) paralisa() End Function paralisa() While Not KeyHit(57) Print "pressione space" Wend End Function

Alterar Volume Podemos alterar o volume de um som por meio do comando SoundVolume. Se voc vai abaixar o volume de um som que j est em execuo, vai precisar usar o canal de som para parar esse som, abaixar o volume, e reativar o canal. Se voc apenas abaixar o som e aplicar o comando PlaySound, vai criar um segundo canal de som. Exemplo 18
meusom = LoadSound("midia\sapo.wav") LoopSound meusom meucanal = PlaySound (meusom) While Not KeyHit(1) x = x + 1 If x = 215 StopChannel meucanal SoundVolume meusom, 0.6 meucanal = PlaySound (meusom) EndIf If x = 500 StopChannel meucanal SoundVolume meusom, 0.2 meucanal = PlaySound (meusom) EndIf Flip Wend

Imagens Jogos 2d e jogos isomtricos so fundamentalmente constitudos por imagens do tipo bitmaps, como arquivos .bmp, .png ou .jpg. O cenrio, os objetos, a vegetao, os personagens, tudo feito de imagens. Veja abaixo um arquivo de dados de imagem de um jogo.

Descarregar um som Jogos normalmente so constitudos de vrias fazes e elas normalmente possuem uma grande quantidade de informao para ser armazenada na memria; coisas como sons, imagens e modelos 3d. O normal que cada fase seja carregada apenas momentos antes de ser iniciada e seja descarregada da memria depois de ser encerrada. Assim temos apenas os dados da

Carregando e exibindo Para esse exemplo estamos usando a imagem abaixo. Ela est na pasta de mdia dos cdigos fontes deste captulo.

Para carregar uma imagem usamos o comando LoadImage. Seu funcionamento semelhante ao comando de carregamento de som. Veja abaixo como se usa esse comando.
minhaimagem = LoadImage(midia\arvore.bmp)

No caso acima, o Blitz j tinha definido como mscara a cor preta, isso 0,0,0. Como a segunda imagem tem o fundo cinza com saturao 170,170,170 ele no apagado e ento ele exibido na tela gerando esse pssimo problema. Para evitar isso temos que configura a mascara de cada imagem manualmente. Mscaras Podemos ajustar a mscara para cada imagem por meio do comando MaskImage, assim exclumos manualmente o fundo de cada imagem. Para trabalhar com esse comando devemos passar o nome da imagem e a cor no padro RGB que usaremos como mscara. Exemplo 22
Graphics 800, 600 arvore= LoadImage("midia\arvore.bmp") arbusto = LoadImage("midia\arbusto.bmp") MaskImage arbusto, 170,170,170 DrawImage arvore, 100, 100 DrawImage arbusto, 200, 220 WaitKey

A segundo coisa necessria ordenar que o Blitz3D exiba a imagem na tela. Isso feito por meio do comando DrawImage. Passamos para esse comando a varivel onde a imagem foi carregada e a posio x, y onde ela dever ser exibida.
DrawImage minhaimagem, 100, 100

Vamos agora a um exemplo completo Exemplo 20


Graphics 800, 600 minhaimagem = LoadImage("midia\arvore.bmp") DrawImage minhaimagem, 100, 100 WaitKey

Imagens animadas Imagens animadas so na verdade uma seqncia de quadros de animao dentro de uma nica imagem. Assim carregamos todos os dados da animao a partir de um nico arquivo para a memria e o Blitz3D cria apontadores para cada frame da animao. Veja abaixo uma imagem com estrutura animada.

Se voc humano, deve estar espantado com a qualidade grfica dessa demonstrao e nesse momento deve estar imaginando o que voc no poderia fazer com esse poder do Blitz3D... Um problema bsico Execute o programa abaixo e veja o que acontece. Exemplo 21
Graphics 800, 600 arvore= LoadImage("midia\arvore.bmp") arbusto = LoadImage("midia\arbusto.bmp") DrawImage arvore, 100, 100 DrawImage arbusto, 200, 220 WaitKey

Veja que uma imagem comum e pode ser carregada e exibida como uma imagem comum. Exemplo 23
Graphics 800, 600 bule= LoadImage("midia\tea.bmp") DrawImage bule, 200, 220 WaitKey

Quando carregamos uma imagem o Blitz3D j define uma mascara padro para imagem. Essa mascara uma cor escolhida como fundo da imagem, ento ela desconsiderada para que o fundo da imagem possa ser apagado. Assim s ficamos com a imagem principal.

A imagem acima foi construda dentro de rgida disposio geomtrica. Cada frame tem 50 x 50 pixels, totalizando uma imagem de 250 x 100. essa estrutura de disposio de cada imagem que permite que o Blitz3D crie um sistema de apontadores para cada frame. Para usar uma imagem animada dinamicamente essa deve ser carregada

como uma imagem animada por meio do comando LoadAnimImage e no momento de sua exibio, com o comando DrawImage, devemos informar qual frame da animao deveremos exibir. Veja como a estrutura do comando LoadAnimImage: LoadAnimImage (nome.tipo, Largura do frame, Altura do frame, primeira, quantidade) Veja que primeiramente devemos informar o nome da imagem. O segundo argumento a largura de cada frame, que no exemplo da nossa imagem ser 50. O terceiro argumento a altura de cada frame, que tambm 50. No quanto argumento dizemos qual a imagem inicial, nesse caso vamos carregar a partir da primeira, ento nossa imagem inicial ser 0. No ultimo argumento dizemos quantos frames vamos carregar; como o ultimo frame da imagem igual ao primeiro, vamos carregar apenas 9. Ento nosso comando fica assim:
chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 0, 9)

diferentes. at comum que alguns jogos tenham praticamente todos os tiles que compe o cenrio de uma fase inteira em apenas um nico arquivo. O prximo exemplo demonstra que uma mesma imagem pode ser exibida quantas vezes voc desejar, por isso no necessrio criar uma varivel para cada vez que a imagem vai ser repetida. Exemplo 25
Graphics 800, 600 chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 5, 1) For x = 0 To 750 Step 50 For y = 0 To 650 Step 50 DrawImage chaleira, x, y, 0 Next Next WaitKey

Temos algumas novidades nesse exemplo.


chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 5, 1)

Para exibir um frame da imagem animada usamos o comando DrawImage e colocamos um ultimo parmetro que diz qual o frame a ser exibido. No exemplo abaixo exibimos o primeiro frame da animao, o frame 0.
DrawImage chaleira, 200, 220, 0

Veja que estamos carregando apenas um frame e estamos carregando a partir do frame 5, que o sexto frame. Portanto essa imagem animada ter apenas um frame que na verdade o sexto frame da imagem.
DrawImage chaleira, x, y, 0

O primeiro parmetro do comando chaleira a imagem animada carregada. O segundo parmetro 200 se refere posio x onde a imagem ser exibida. O terceiro parmetro 220 a posio y onde a imagem aparecer. Por fim, o 0 o frame da imagem que vai ser mostrado. Veja um exemplo completo que carrega e exibe todos os frames de uma imagem animada. Exemplo 24
Graphics 800, 600 chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 0, 9) DrawImage chaleira, 100, 120, 0 DrawImage chaleira, 150, 170, 1 DrawImage chaleira, 200, 220, 2 DrawImage chaleira, 250, 270, 3 DrawImage chaleira, 300, 320, 4 DrawImage chaleira, 350, 370, 5 DrawImage chaleira, 400, 420, 6 DrawImage chaleira, 450, 470, 7 DrawImage chaleira, 500, 520, 8 WaitKey

Veja que estamos exibindo o frame 0. No confunda os frame do arquivo da imagem com os frame carregados. O comando LoadImage carrega frames de um arquivo e quando apontamos para ele o frame 5 foi como se dissssemos Carregue o sexto frame desse arquivo. Mas a partir desse momento, esse arquivo no faz parte da lgica, e como carregamos apenas 1 frame, esse frame que era o 5 do arquivo agora o frame 0 da varivel de imagem animada.
For x = 0 To 750 Step 50 For y = 0 To 650 Step 50 DrawImage chaleira, x, y, 0 Next Next

Nesse exemplo voc pode perceber que podemos usar cada imagem individualmente. por isso que, como voc viu no incio, um arquivo pode conter diversas coisas

Como nossa imagem tem 50 x 50, tambm incrementamos os loops em 50 unidades por meio de Step 50. Assim as imagens j se enquadram diretamente no local que devero se exibidas. Veja que estamos usando as variveis do loop como posio x e y para exibio das imagens. E a animao? Para criar um sistema de animao basta criarmos uma varivel contador e uma varivel frame. Usaremos o comando Flip no modo grfico assim a velocidade de execuo ser sincronizada com o retrao do

monitor, o que mais ou menos 60 ciclos por segundo. Vamos primeiro criar uma animao de 12 quadros por segundo. O primeiro passo achar qual dever ser o valor limite do contador. 60/12 = 5, assim, para conseguirmos uma animao de 12 quadros por segundo, deveremos incrementar um frame a cada 5 unidade do contador. A estrutura seria assim.
contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 End If

No exemplo a seguir, demonstramos o poder de animao enchendo a tela de imagens animadas. Exemplo 28
Graphics 800, 600 chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 0, 9) frame = 0 contador = 0 While Not KeyHit(1) contador = contador + 1 If contador = 3 contador = 0 frame = frame + 1 End If If frame = 9 Then frame = 0 For x = 0 To 750 Step 50 For y = 0 To 650 Step 50 DrawImage chaleira, x, y, frame Next Next Flip Cls Wend

Veja que para cada vez que o contador atingir o valor limite 5 devemos passar a animao para o prximo frame, assim teremos a velocidade desejada. Mas ainda falta colocar o controle para que animao no passe no ultimo quadro, seno dar erro:
If frame = 9 Then frame = 0

Isso reinicia a animao para o primeiro frame, colocando-a em loop. Vamos ao exemplo! Exemplo 26
Graphics 800, 600 chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 0, 9) frame = 0 contador = 0 While Not KeyHit(1) contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 End If If frame = 9 Then frame = 0 DrawImage chaleira, 375, 275, frame Flip Cls Wend

Um ultimo detalhe:
Flip Cls

Como voc se lembra, o comando Flip tem duas finalidades: colocar a imagem no buffer de vdeo e controlar a velocidade de execuo do loop do jogo. Abaixo dele est o comando Cls, que composto pelas iniciais de Clear Screen, isso , limpar a tela. O que esse comando faz limpar as imagens anteriores da tela para que elas no vo se sobrepondo umas as outras. Experimente tirar o Cls do programa e veja o que acontece. FreeImage Para descarregar uma imagem da memria usamos o comando FreeImage sobre a varivel na qual a imagem foi carregada.
FreeImage chaleira

No prximo exemplo demos uma turbinada na animao, colocamos em 30 quadros por segundo. Exemplo 27
Graphics 800, 600 chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 0, 9) frame = 0 contador = 0 While Not KeyHit(1) contador = contador + 1 If contador = 2 contador = 0 frame = frame + 1 End If If frame = 9 Then frame = 0 DrawImage chaleira, 375, 275, frame Flip Cls Wend

Exemplo 29
Graphics 800, 600 chaleira= LoadAnimImage("midia\tea.bmp", 50, 50, 0, 9) DrawImage chaleira, 200, 200, 1 Print "Pressione uma tecla para descarregar" WaitKey FreeImage chaleira DrawImage chaleira, 200, 200, 1 WaitKey

Veja nesse exemplo que o primeiro comando de exibio funciona normalmente, mas a segunda vez que o comando usado vem depois de descarregar a imagem. Isso causa um erro, pois a imagem no existe mais. Animaes

Como voc j percebeu as animaes de um jogo 2D so uma srie de imagens estticas que, devido ao fato de serem elaboradas numa seqncia de momentos, criam a iluso de o personagem estar em movimento. Voc tem a liberdade de fazer essas imagens da forma que desejar, mas a tcnica para conseguir o melhor resultado com menor esforo criar essas imagens a partir de um modelador 3D com render, como Blender, 3DS Max, Maya, Cinema4D, etc. Criar as imagens em um modelar da melhor qualidade de iluminao e deixa a mesma mais realista, alm do que voc s tem o trabalho de fazer o modelo uma vez e depois a ferramenta gera automaticamente vrias posies e perspectivas diferentes do mesmo trabalho. Animao com duas cmeras Essa a maneira mais primitiva de animao. Ela o estilo de animao das plataformas mais antigas, onde os processadores no tinham um grande poder de processamento. Animaes nesse estilo possuem uma perspectiva lateral do personagem que s se move para frente ou para trs. So exemplos desse tipo de animao o Jogo Sonic, os primeiros jogos do Mario e a grande maioria dos jogos de plataformas at 16 bits. Veja abaixo um exemplo de animao em duas cmeras.

robo = LoadAnimImage("midia\robo2c.bmp", 50, 80, 0, 16) frame = 0 contador = 0 px = 200 py = 200 While Not KeyHit(1) contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 End If If frame = 16 Then frame = 0 DrawImage robo, px, py, frame Flip Cls Wend

Vamos agora aprender a fazer controle de animaes de duas cmeras para personagens do jogo. O que temos a fazer criar 4 sries de animaes diferente: uma parada olhando a direita, outra andando para a direita, a terceira parado olhando a esquerda e por ltimo andando para a esquerda. Essas animaes vo ser controladas por chaves que sero acionadas por meio das teclas de setas. Exemplo 31
Graphics 800, 600 SetBuffer BackBuffer() robo = LoadAnimImage("midia\robo2c.bmp", 50, 80, 0, 16) frame = 0 contador = 0 anima = 1 ; 1 = parado direita, ; 2 = andando direita ; 3 = parado esquerda ; 4 = andando esquerda px = 375 py = 260 While Not KeyHit(1) ;------------------ input ------------------If KeyDown(205) If anima <> 2 anima = 2 contador = 0 Frame = 0 EndIf Else If anima = 2 Then anima = 1 EndIf If KeyDown(203) If anima <> (4) anima = 4 contador = 0 Frame = 8 EndIf Else If anima = 4 Then anima = 3 EndIf ;------------------ logica ----------------If anima = 2 contador = contador + 1

Esse arquivo de imagem animado foi feito a partir de um modelo 3d que vem junto com o Blitz3D. Foi importado para o 3ds Max, posicionamos uma cmera na lateral esquerda do rob e outras na lateral direita e renderizamos alguns quadros da animao original do modelo. O passo seguinte foi montar todos os quadros em uma s imagem por meio de um programa de tratamento de imagens. Vamos ver o resultado disso? O exemplo abaixo exibe todas as animaes presentes na imagem animada. Exemplo 30
Graphics 800, 600

If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 8 Then frame = 0 EndIf If anima = 4 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 16 Then frame = 8 EndIf ;-------------------Exibe -----------------If anima = 1 DrawImage robo, px, py, 0 If anima = 3 DrawImage robo, px, py, 8 If anima = 2 DrawImage robo, px, py, frame If anima = 4 DrawImage robo, px, py, frame Flip Cls Wend

Caso a tecla de seta a direita no esteja pressionada, devemos verificar se a animao que est ativa a animao para a direita para que possamos par-la se isso for verdadeiro. Assim, se ela ainda no foi parada, colocamos ela no estado 1 que olhando para a direita. Essa estrutura lgica causa o efeito imediato de paralisar a animao e fazer o rob olhar para o lado que estava andando.
If KeyDown(203) If anima <> (4) anima = 4 contador = 0 Frame = 8 EndIf Else If anima = 4 Then anima = 3 EndIf

Explicando...
frame = 0 contador = 0

Essas variveis j so nossas conhecidas no mesmo? Se voc na se lembra, de uma olhada nos exemplos anteriores.
anima ; 2 = ; 3 = ; 4 = = 1 ; 1 = parado direita, andando direita parado esquerda andando esquerda

Esse trecho de cdigo idntico ao explicado anteriormente, mas para o outro lado da animao. Bem por isso ao reiniciar os estados da animao o frame inicial o 8 Frame=8, pois agora o rob vai andar para o lado contrrio.
If anima = 2 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 8 Then frame = 0 EndIf If anima = 4 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 16 Then frame = 8 EndIf

Criamos uma varivel para ser a chave da animao, isso : ela responsvel por ativar as animaes e informar o estado atual delas. Ao lado fizemos anotaes para no esquecermos o que cada estado representa.
px = 375 py = 260

Essas duas variveis representam a posio x e y onde a animao vai aparecer.


If KeyDown(205) If anima <> 2 anima = 2 contador = 0 Frame = 0 EndIf

Se a tecla seta a direita estiver pressionada iremos verificar se o estado da animao no o andando para a direita. Isso necessrio, pois se j estivermos andando para a direita no podemos reiniciar a animao. Sem essa chave a animao no sairia do primeiro quadro. Se a animao atual diferente de 2 ento vamos iniciar a animao 2 anima=2 e reiniciar os estados do contador contador=0 e do frame atual Frame=0.
Else If anima = 2 Then anima = 1 EndIf

O cdigo acima j foi estudado em programas anteriores. Ele o responsvel por fazer o controle dos frames que devem ser exibidos. O diferencial que apresenta aqui que agora so duas animaes separadas e por isso tivemos que separar o cdigo em dois blocos controlado pela chave de animao. Se a chave igual a 2 If anima=2 a animao vai de 0 a 7 If frame=8 Then frame=0. E se for igual a 4 If anima=4 a animao vai de 8 a 15 If frame=16 Then frame=8.
;-------------------Exibe -----------------If anima = 1 DrawImage robo, px, py, 0 If anima = 3 DrawImage robo, px, py, 8 If anima = 2 DrawImage robo, px, py, frame If anima = 4 DrawImage robo, px, py, frame

Por fim a estrutura de exibio das imagens. Se a chave est nas imagens estticas, sem mistrio, exibem s um frame. Caso ela esteja em um dos estados animados, usamos a varivel frame para exibir o frame atual da animao.
Flip Cls Wend

If KeyDown(203) Then CONTROLE_FX = CONTROLE_FX + 2

O que cria a iluso de movimento so as linhas de cdigo abaixo, pois as imagens no so exibidas em um local fixo, mas tem seu local de exibio derivado da soma da posio inicial + a varivel FX que varia de valor. Assim a posio em que ser exibida varia junto com o valor dessa varivel.
DrawImage arvore, 170 + CONTROLE_FX, 140 DrawImage arvore, 700 + CONTROLE_FX, 120

No vamos esquecer o comando de atualizao do buffer e de apagar as imagens antigas. Colocando um pouco de vida Vamos colocar algumas rvores e arbustos no programa anterior para dar uma sensao de maior realismo no movimento. Afinal, sem alguns objetos se movendo na tela, temos apenas a impresso de animao, mas no temos uma sensao real de movimento. Uma animao em um jogo 2D ao contrrio da vida real. Enquanto na vida real o personagem anda e o cenrio fica esttico, em um jogo 2D todo o cenrio se move e o personagem o nico a ficar esttico. Para criar esse efeito usamos uma matemtica muito simples onde a posio x de cada objeto do cenrio dada por uma funo F(x) = posio + x. Cada objeto do cenrio tem uma posio relativa inicial e sua posio x real ser igual a essa posio mais o fator x. Quando apertarmos os botes direcionais o fator x vai ser aumentando ou diminudo e como a posio o objeto sua posio mais o fator x, ela vai ser alterada. O exemplo abaixo mostra esse efeito. Exemplo 32
Graphics 800, 600 SetBuffer BackBuffer() arvore = LoadImage("midia\Arvore.bmp") CONTROLE_FX = 0 While Not KeyHit(1) If KeyDown(205) Then CONTROLE_FX = CONTROLE_FX - 2 If KeyDown(203) Then CONTROLE_FX = CONTROLE_FX + 2 DrawImage arvore, 170 + CONTROLE_FX, 140 DrawImage arvore, 700 + CONTROLE_FX, 120 Flip Cls Wend

Agora que voc j sabe como funciona, vamos colocar umas rvores e arbustos no programa de animao do rob para dar um pouco mais de realismo.

Exemplo 33
Graphics 800, 600 SetBuffer BackBuffer() robo = LoadAnimImage("midia\robo2c.bmp", 50, 80, 0, 16) arvore = LoadImage("midia\Arvore.bmp") arbusto = LoadImage("midia\arbusto.bmp") MaskImage arbusto, 170,170, 170 frame = 0 contador = 0 anima = 1 ; 1 = parado direita, ; 2 = andando direita ; 3 = parado esquerda ; 4 = amdando esquerda px = 375 py = 260 CONTROLE_FX = 0 While Not KeyHit(1) ;------------------ input ------------------If KeyDown(205) If anima <> 2 anima = 2 contador = 0 Frame = 0 EndIf CONTROLE_FX = CONTROLE_FX - 2 Else If anima = 2 Then anima = 1 EndIf If KeyDown(203) If anima <> (4)

Como voc pode ver, iniciamos nossa varivel de controle F(x) em zero:
CONTROLE_FX = 0

E, com a apertar das setas direcionais, essa varivel vai sendo incrementada ou decrementada.
If KeyDown(205) Then CONTROLE_FX = CONTROLE_FX - 2

anima = 4 contador = 0 Frame = 8 EndIf CONTROLE_FX = CONTROLE_FX + 2 Else If anima = 4 Then anima = 3 EndIf ;------------------ logica ----------------If anima = 2 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 8 Then frame = 0 EndIf If anima = 4 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 16 Then frame = 8 EndIf ;-------------------Exibe -----------------;arvores DrawImage arvore, -300 + CONTROLE_FX, 100 DrawImage arvore, 70 + CONTROLE_FX, 140 DrawImage arvore, 700 + CONTROLE_FX,120 DrawImage arbusto, -100 + CONTROLE_FX, 210 DrawImage arbusto, 300 + CONTROLE_FX, 190 ;robo If anima = 1 DrawImage robo, px, py, 0 If anima = 3 DrawImage robo, px, py, 8 If anima = 2 DrawImage robo, px, py, frame If anima = 4 DrawImage robo, px, py, frame Flip Cls Wend

;-------------------Exibe -----------------;arvores DrawImage arvore, -300 + CONTROLE_FX, 100 DrawImage arvore, 70 + CONTROLE_FX, 140 DrawImage arvore, 700 + CONTROLE_FX, 120 DrawImage arbusto, -100 + CONTROLE_FX, 210 DrawImage arbusto, 300 + CONTROLE_FX, 190

Como a vegetao uma composio de fundo, devemos exibi-las antes do rob, seno elas ficariam sobre ele na ordem de empilhamento. Animao com 4 cmeras As animaes em quatro cmeras so mais comuns em jogos no estilo rpg, onde existe uma certa liberdade em explorar o territrio. As animaes so criadas a partir de quatro ngulos de viso que normalmente so para direita, para a esquerda, para cima e para baixo. As cmeras normalmente tambm possuem uma certa inclinao, pegando uma viso a partir de cima do personagem, algo em torno de um ngulo de 30 a 45 graus, pois esses jogos possuem perspectiva, j que o personagem se move para todas as regies de um mapa.

Vamos ver o que mudou nesse programa.


arvore = LoadImage("midia\Arvore.bmp") arbusto = LoadImage("midia\arbusto.bmp") MaskImage arbusto 170 170, 170

Agora estamos carregando arvores e arbustos tambm. Aplicamos uma mscara na imagem do arbusto que possui um fundo cinza.
CONTROLE_FX = 0

Agora o programa tambm tem uma varivel F(x).


CONTROLE_FX = CONTROLE_FX + 2 CONTROLE_FX = CONTROLE_FX - 2

Essa imagem acima representa os 4 eixos de animao de um jogo com animao em quatro cmeras. Um exemplo recente desse tipo de jogo o Magnfico RPG Fire Emblem: The Sacred Stones, da Nintendo, desenvolvido para o Game Boy Advanced. Jogos em 4 cmeras tambm podem ser feitos com a tcnica de isometria e nesse caso as cmeras e os movimentos so diagonais. Um exemplo desse caso o famoso jogo Final Fantasy Tatics. Veja abaixo um arquivo animado com 4 cmeras para um personagem.

Dentro dos controles de input de teclado estamos alterando o valor da varivel de controle de rolagem de objetos F(x) para criar a sensao de movimento.

No exemplo abaixo, usamos a tcnica para animar um personagem em 4 cmeras. Exemplo 34


Graphics 800, 600 SetBuffer BackBuffer() robo = LoadAnimImage("midia\robo4c.png", 50, 50, 0, 32) MaskImage robo, 255, 255, 255 frame = 0 contador = 0 anima = 1 ; 1 = parado direita ; 2 = andando direita ; 3 = parado esquerda ; 4 = andando esquerda ; 5 = parado acima ; 6 = andando acima ; 7 = parado abaixo ; 8 = andando abaixo px = 375 py = 260 While Not KeyHit(1) ;------------------ input ------------------If KeyDown(205) If anima <> 2 anima = 2 contador = 0 Frame = 0 EndIf Else If anima = 2 Then anima = 1 EndIf If KeyDown(203) If anima <> (4) anima = 4 contador = 0 Frame = 8 EndIf Else If anima = 4 Then anima = 3 EndIf If KeyDown(200) If anima <> (6) anima = 6 contador = 0 Frame = 16 EndIf Else If anima = 6 Then anima = 5 EndIf If KeyDown(208) If anima <> (8) anima = 8 contador = 0 Frame = 24 EndIf

Else If anima = 8 Then anima = 7 EndIf ;------------------ logica ----------------If anima = 2 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 8 Then frame = 0 EndIf If anima = 4 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 16 Then frame = 8 EndIf If anima = 6 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 24 Then frame = 16 EndIf If anima = 8 contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 EndIf If frame = 32 Then frame = 24 EndIf ;-------------------Exibe -----------------If anima = 1 DrawImage robo, px, py, 0 If anima = 3 DrawImage robo, px, py, 8 If anima = 5 DrawImage robo, px, py, 16 If anima = 7 DrawImage robo, px, py, 24 If anima = 2 DrawImage robo, px, py, frame If anima = 4 DrawImage robo, px, py, frame If anima = 6 DrawImage robo, px, py, frame If anima = 8 DrawImage robo, px, py, frame Flip Cls Wend

Perceba que esse programa no possui nenhuma novidade em relao ao programa que manipula a animao em duas cmeras. S adicionamos novos controles semelhantes aos anteriores, para manipular as animaes adicionadas. Como essa animao maior, estamos usando o formato de arquivo .png que compactado. Para trabalhar com esse arquivo temos que definir a rea de transparncia e salvar sem suavizaes,

para que a imagem no seja alterada, seno no possvel fazer a mascara de imagem (o colorkey). Animaes com 8 cmeras Os melhores jogos 2D so criados baseados em um sistema de animao com 8 cmeras. Alguns deles so to bem desenvolvidos, como Age Of Empires e Diablo II, que a maioria das pessoas no sabem distinguir se um jogo 2D ou se um jogo 3D. Voc saberia distinguir? bem simples, em um jogo 2D s personagens possuem efeito de animao em vrios ngulos. Em um jogo 3D todo o cenrio capaz de rotacionar e no apenas os personagens. O grfico abaixo mostra os ngulos de animao em um sistema com 8 cmeras, ou 8 direes.

Graphics 800, 600 robo= LoadAnimImage("midia\robo8c.png", 50, 50, 0, 64) MaskImage robo, 255, 255, 255 frame = 0 contador = 0 While Not KeyHit(1) contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 End If If frame = 64 Then frame = 0 DrawImage robo, 375, 275, frame Flip Cls Wend

Um jogo nesse estilo tem uma grande demanda de memria, pois cada personagem tem todas as suas animaes em oito perspectivas diferentes. Veja abaixo um arquivo com animaes em 8 cmeras.

Para fazer o controle da animao via teclado devemos implementar uma tcnica diferente, pois as animaes diagonais dependem de duas teclas e as animaes dos quatro eixos principais, apenas de uma tecla. Mas todas as animaes vo possuir pelo menos 1 tecla em comum com outras duas animao, por exemplo, tanto o movimentar a direita, como o movimentar a direita e acima e o movimentar a direita e abaixo dependem da tecla de seta direita. Isso pode causar um colapso na animao se no for bem administrado. Vamos abaixo dar um exemplo de uma tcnica errada, causando um colapso na animao. Esse exemplo tenta implementar as trs animaes descritas acima. Exemplo 36 (Erro Lgico)
Graphics 800, 600 robo= LoadAnimImage("midia\robo8c.png", 50, 50, 0, 64) MaskImage robo, 255, 255, 255 frame = 0 contador = 0 anima = 0 While Not KeyHit(1) contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 End If If KeyDown(205) If anima <> (1) anima = 1 contador = 0 Frame = 0 EndIf If frame > 7 Then frame = 0 Else If anima = 1 Then anima = 0 EndIf If KeyDown(205) And KeyDown(208) If anima <> (2) anima = 2 contador = 0 Frame = 8 EndIf

O exemplo abaixo roda todas as animaes dessa imagem animada. Exemplo 35

If frame > 15 Then frame = 8 Else If anima = 2 Then anima = 0 EndIf If KeyDown(205) And KeyDown(200) If anima <> (8) anima = 8 contador = 0 Frame = 56 EndIf If frame > 63 Then frame = 56 Else If anima = 8 Then anima = 0 EndIf If anima = 0 Then DrawImage robo, 275, 0 If anima = 1 Then DrawImage robo, 275, frame If anima = 2 Then DrawImage robo, 275, frame If anima = 8 Then DrawImage robo, 275, frame Flip Cls Wend

375, 375, 375, 375,

Como voc j deve ter percebido, s a animao para a direita funciona. O problema dessa implementao que verificamos se a tecla 205 est pressionada em 3 locais. Quando pressionamos as teclas para direita e para cima, liberado o movimento diagonal nesse sentido, mas tambm liberado o movimento para a direita, assim a animao nunca passa do primeiro frame de cada animao. No entanto, quando s pressionamos a tecla para direita, s a animao para a direita liberada, por isso ela a nica que funciona. Veja como foi feita essa lgica errada Condio1; Condio2; Condio3; If Condio1 => ao1 If Condio2 e Condio1 => ao2 If Condio3 e Condio1 => ao3 Veja como seria o Correto If Condio1 If Condio2 => ao2 Else If Condio3 => ao3 Else => ao1 EndIf EndIf Nesse sistema acima cada condio ser verificada apenas 1 vez e no ir causar colapso na animao. Quer a prova? Vamos l! Execute o prximo exemplo. Exemplo 37

Graphics 800, 600 SetBuffer BackBuffer() robo= LoadAnimImage("midia\robo8c.png", 50, 50, 0, 64) MaskImage robo, 255, 255, 255 frame = 0 contador = 0 anima = 0 While Not KeyHit(1) ;--------------- CONTROLADOR --------------contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 End If ;------------------INPUTS------------------If KeyDown(205) If KeyDown(208) ; DIREITA E ABAIXO If anima <> (2) anima = 2 contador = 0 Frame = 8 EndIf If frame > 15 Then frame = 8 Else If KeyDown(200) ;DIREITA E ACIMA If anima <> (8) anima = 8 contador = 0 Frame = 56 EndIf If frame > 63 Then frame = 56 Else ;DIREITA If anima <> (1) anima = 1 contador = 0 Frame = 0 EndIf If frame > 7 Then frame = 0 EndIf Else anima = 0 EndIf ;------------------------EXIBE--------------------If anima = 0 Then DrawImage robo, 375, 275, 0 If anima > 0 Then DrawImage robo, 375, 275, frame Flip Cls Wend

Agora funcionou direitinho... Que tal mais um exemplo com as oito animaes? Exemplo 38
Graphics 640, 480, 16, 1 SetBuffer BackBuffer() robo= LoadAnimImage("midia\robo8c.png", 50, 50, 0, 64) MaskImage robo, 255, 255, 255 frame = 0 contador = 0 anima = 0

parado = 0 While Not KeyHit(1) ;--------------- CONTROLADOR --------------contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 End If ;------------------INPUTS------------------TECLA_DIREITA = KeyDown(205) TECLA_ESQUERDA = KeyDown(203) TECLA_ACIMA = KeyDown(200) TECLA_ABAIXO = KeyDown(208) If TECLA_DIREITA If TECLA_ABAIXO ; DIREITA E ABAIXO If anima <> (2) anima = 2 contador = 0 Frame = 8 EndIf If frame > 15 Then frame = 8 Else If TECLA_ACIMA ;DIREITA E ACIMA If anima <> (8) anima = 8 contador = 0 Frame = 56 EndIf If frame > 63 Then frame = 56 Else ;DIREITA If anima <> (1) anima = 1 contador = 0 Frame = 0 EndIf If frame > 7 Then frame = 0 EndIf EndIf ; ACIMA If TECLA_ACIMA If Not TECLA_ESQUERDA If Not TECLA_DIREITA If anima <> (7) anima = 7 contador = 0 Frame = 48 EndIf If frame > 55 Then frame = 48 EndIf EndIf EndIf ; ABAIXO If TECLA_ABAIXO If Not TECLA_ESQUERDA If Not TECLA_DIREITA If anima <> (3) anima = 3 contador = 0 Frame = 16 EndIf If frame > 23 Then frame = 16 EndIf EndIf

EndIf If TECLA_ESQUERDA If TECLA_ABAIXO ;ESQUERDA E ABAIXO If anima <> (4) anima = 4 contador = 0 Frame = 24 EndIf If frame > 31 Then frame = 24 Else If TECLA_ACIMA ;ESQUERDA E ACIMA If anima <> (6) anima = 6 contador = 0 Frame = 40 EndIf If frame > 47 Then frame = 40 Else ;ESQUERDA If anima <> (5) anima = 5 contador = 0 Frame = 32 EndIf If frame > 39 Then frame = 32 EndIf EndIf ;SE NENHUMA TECLA FOI PRESSIONADA If Not TECLA_ACIMA If Not TECLA_ABAIXO If Not TECLA_ESQUERDA If Not TECLA_DIREITA If anima > 0 parado = (anima * 8) - 8 EndIf Anima = 0 EndIf EndIf EndIf EndIf ;------------------------EXIBE--------------------If anima = 0 Then DrawImage robo, 300, 200, parado If anima > 0 Then DrawImage robo, 300, 200, frame Flip Cls Wend

Explicando as novidades...
parado = 0

Criamos uma varivel para controlar o frame do estado de animao parado (anima=0) dinamicamente.
TECLA_DIREITA = KeyDown(205) TECLA_ESQUERDA = KeyDown(203) TECLA_ACIMA = KeyDown(200) TECLA_ABAIXO = KeyDown(208)

Ao invs de ficar testando vrias vezes o buffer de teclado, o que consumiria recursos de processamento, fazemos apenas um teste por ciclo para cada tecla e colocamos o resultado em variveis.
If TECLA_DIREITA If TECLA_ABAIXO

Para controlar as animaes, agora testamos essas variveis para teclas e no o buffer do teclado.
; ACIMA If TECLA_ACIMA If Not TECLA_ESQUERDA If Not TECLA_DIREITA If anima <> (7) anima = 7 contador = 0 Frame = 48 EndIf If frame > 55 Then frame = 48 EndIf EndIf EndIf

Para acionarmos a animao para cima, a tecla de seta para cima deve estar pressionada e as teclas para esquerda e para direita no podem estar, seno teramos aquele velho problema de colapso de animao. Por isso tivemos que fazer esse conjunto de verificaes if aninhados.
; ABAIXO If TECLA_ABAIXO If Not TECLA_ESQUERDA If Not TECLA_DIREITA If anima <> (3) anima = 3 contador = 0 Frame = 16 EndIf If frame > 23 Then frame = 16 EndIf EndIf EndIf

O mesmo verdadeiro para animao para baixo.


;SE NENHUMA TECLA FOI PRESSIONADA If Not TECLA_ACIMA If Not TECLA_ABAIXO If Not TECLA_ESQUERDA If Not TECLA_DIREITA If anima > 0 parado = (anima * 8) - 8 EndIf Anima = 0 EndIf EndIf EndIf EndIf

O ultimo problemas a ser vencido a implementao do estado parado. Para ativarmos este estado tivemos que fazer 4 verificaes if para saber se nenhuma das quatro teclas de movimento estavam sendo pressionadas. O ultimo desafio foi colocar a imagem parada no mesmo sentido que estava andando. Para isso colocamos uma verificao se o primeiro momento como parada If anima > 0, isso , se antes de agora, ela estava sendo animada. Se isso

verdadeiro fazemos o frame de animao parado, que se chama parado igual a uma frmula que fornece o primeiro frame da animao anterior parado = (anima * 8) 8. Isso faz com que o rob fique parado no mesmo sentido que estava andando. Com isso aprendemos praticamente todos os fundamentos de tcnicas de animaes de personagens 2D. Mais pela frente, ns vamos estudar de maneira mais profunda a animao de cenrios com tcnicas de scrolling e mapas de tiles. COLISES A deteco de colises algo essencial na maioria dos jogos. por meio dela que um personagem impedido de atravessar paredes, perde vida ao receber um tiro, salta, pega itens, etc. Em imagens mais simples, como um cubo ou um crculo as colises podem ser verificadas matematicamente, mas nas mais complexas, com formas mais singulares, fica invivel aplicar esse tipo de tcnica com preciso. O Blitz3D possui um poderoso e veloz sistema de colises que funciona por meio de verificao de pixels das imagens. Assim ele vai fazer a verificao de colises apenas da rea da imagem que est sendo exibida na tela, desprezando a rea invisvel da mscara. Colises Simples Por meio do comando ImagesOverlap o Blitz3D fornece um sistema de colises de imagens muito rpido, mas sem preciso de transparncia. Para que esse comando funcione devemos passar para ele 6 parmetros: a primeira imagem a ser verificada, sua posio x, sua posio y, a segunda imagem, a sua posio x e sua posio y. Portanto, esse comando possui a seguinte assinatura: ImagesOverlap( imagem1, x1, y1, imagem2, x2, y2) Veja no exemplo abaixo o uso que ImagesOverlap. Use o mouse para controlar a posio da bola. Como voc poder perceber, esse comando no leva em considerao a transparncia da imagem e por isso no oferece colises precisas. Exemplo 39
Graphics 800, 600 SetBuffer BackBuffer() arvore = LoadImage("midia\Arvore.bmp") bola = LoadImage("midia\bola.png") While Not KeyHit(1) px = MouseX()

py = MouseY() If ImagesOverlap(bola, px, py, arvore, 100, 100) Text 300, 20, "-X- COLIDINDO -X-" EndIf DrawImage arvore, 100, 100 DrawImage bola, px, py Flip Cls Wend

o frame atual da animao, s usar essa varivel como parmetro, tanto para exibir a imagem, como para dizer com qual frame se dar a coliso. Exemplo 41
Graphics 800, 600 SetBuffer BackBuffer() bola = LoadImage("midia\bola.png") ponta = LoadAnimImage("midia\ponta.png", 100,40,0,4) frame = 0 controle = 0 While Not KeyHit(1) controle = controle + 1 If controle = 20 frame = frame + 1 controle = 0 EndIf If frame = 4 Then frame = 0 If ImagesCollide(bola, 300, 250, 0, ponta, 221, 253, frame) Text 300, 20, "-X- COLIDINDO -X-" EndIf DrawImage ponta, 221, 253, frame DrawImage bola, 300, 250 Flip Cls Wend

Colises Precisas Se desejarmos um perfeito controle de colises ento devemos fazer uso do comando ImagesCollide. Esse comando oferece uma preciso por pixels e leva em considerao a transparncia da imagem. A assinatura desse comando um pouco mais complexa, pois tambm devemos colocar o frame da animao atual da imagem. Se a imagem no animada, deixe como 0. Veja: ImagensCollide(imagem1, x1, y1, frame, imagem2, x2, y2, frame) Como cada frame de uma imagem animada pode possuir objetos totalmente diferentes, necessrio fornecer esse parmetro adicional. Veja o exemplo anterior, mas agora com maior preciso graas ao uso de ImagesCollide. Exemplo 40
Graphics 800, 600 SetBuffer BackBuffer() arvore = LoadImage("midia\Arvore.bmp") bola = LoadImage("midia\bola.png") While Not KeyHit(1) px = MouseX() py = MouseY() If ImagesCollide(bola, px, py, 0, arvore, 100, 100, 0) Text 300, 20, "-X- COLIDINDO -X-" EndIf DrawImage arvore, 100, 100 DrawImage bola, px, py Flip Cls Wend

Veja a baixo as linhas correspondentes a essa tecnica:


ImagesCollide(bola, 300, 250, 0, ponta, 221, 253, frame)

Veja que usamos o frame O de cada imagem: If ImagesCollide(bola, px, py, 0, arvore, 100, 100, 0) Agora sim as colises esto perfeitas... Colises com imagens animadas Para conseguirmos um efeito perfeito de coliso com imagens animadas basta usarmos o mesmo frame da animao para a verificao da coliso. O exemplo abaixo faz isso dinamicamente. Como temos uma imagem com animao e possumos uma varivel frame que contem

Aqui usamos varivel frame para testar dinamicamente o frame atual da animao. DrawImage ponta, 221, 253, frame A mesma varivel usada para exibir a animao, por isso temos um sincronismo da exibio coma a fsica de coliso. Detectando tiros O que realmente importante saber em tcnicas de tiro e suas relaes com colises que ao ser detectada uma coliso de um tiro com um personagem, devem ser disparados eventos relativos a esse fato. Por exemplo, um tiro normalmente destri, mata um personagem, explode um objeto, contabiliza pontos... Veja o exemplo abaixo. Exemplo 42
Graphics 800, 600 SetBuffer BackBuffer() tiro = LoadImage("midia\foguete.png") barril = LoadAnimImage("midia\barril.png", 50,40,0,4) MaskImage barril, 255, 255, 255 frame = 0 controle = 0 STATE = 0 PONTOS = 0 TOTAL_TIROS = 0 TIROS_CERTOS = 0

px = 400 py = 500 barrilx = Rnd(50, 750) barrily = Rnd(50, 200) While Not KeyHit(1) ;STATE = 0 normal ;STATE = 1 atirando ;STATE = 2 explodindo If STATE = 0 px = MouseX() EndIf If STATE = 1 py = py - 2 If py < 0 py = 500 STATE = 0 EndIf EndIf If STATE = 2 controle = controle + 1 If controle = 5 frame = frame + 1 controle = 0 EndIf If frame = 4 frame = 0 STATE = 0 barrilx = Rnd(50, 750) barrily = Rnd(20, 200) EndIf EndIf If ImagesCollide(tiro, px, py, 0, barril, barrilx, barrily, 0) STATE = 2 py = 500 TIROS_CERTOS = TIROS_CERTOS + 1 PONTOS = PONTOS + (205 - barrily) EndIf If MouseHit(1) If STATE = 0 STATE = 1 TOTAL_TIROS = TOTAL_TIROS + 1 EndIf EndIf DrawImage barril, barrilx, barrily, frame DrawImage tiro, px, py Text 100, 0, "PONTOS: " + PONTOS Text 350, 0, "TOTAL DE TIROS: " + TOTAL_TIROS Text 540, 0, "TIROS NO ALVO: " + TIROS_CERTOS Flip Cls Wend

colocamos todos esses eventos como sincrnicos, mas em um jogo real eles so assncronos, tendo suas linhas de eventos independentes e variveis prprias para gerenciar esses eventos. Tambm criamos variveis para pontos, total de tiros disparados, tiros certos e para a posio atual do tiro.
barrilx = Rnd(50, 750) barrily = Rnd(50, 200)

A posio do barril ser aleatria, dentro de certos limites.


If STATE = 0 px = MouseX() EndIf

E estivermos em estado normal do jogo, a posio x do tiro, isso , do nosso foguete a posio x do mouse. Assim, enquanto no est em estado de disparado, o foguete obedece ao mouse.
If STATE = 1 py = py - 2 If py < 0 py = 500 STATE = 0 EndIf EndIf

O estado 1 de tiro se movendo. Por isso a varivel da posio y do tiro est sendo decrementada py = py - 2, isso , o tiro se move para cima. Se o tiro chegou at em cima da tela If py < 0, ento sinal que ele errou o alvo, assim colocamos ele de volta a posio inicial py = 500 e mudamos o status do jogo para normal STATE = 0 para que o mouse volte a controlar o mesmo.
If STATE = 2 controle = controle + 1 If controle = 5 frame = frame + 1 controle = 0 EndIf If frame = 4 frame = 0 STATE = 0 barrilx = Rnd(50, 750) barrily = Rnd(20, 200) EndIf EndIf

Explicando...
STATE = 0 PONTOS = 0 TOTAL_TIROS = 0 TIROS_CERTOS = 0 px = 400 py = 500

Esse bloco de cdigo o controle do estado 2 isso , da animao da exploso. Veja as pastes mais importantes desse bloco:
controle = controle + 1

Esse o contador do tempo da animao.


If controle = 5 frame = frame + 1 controle = 0 EndIf

Criamos vrias variveis de controle. A varivel STATE dir qual o estado atual do jogo, se esta em estado normal, com tiro em ao ou explodido. Nesse exemplo,

Se o contador chegar a 5 avana uma frame da animao e reinicia o contador


If frame = 4

frame = STATE = barrilx barrily EndIf

0 0 = Rnd(50, 750) = Rnd(20, 200)

Text 540, 0, "TIROS NO ALVO: " + TIROS_CERTOS

Se a animao chegou at o ultimo frame reiniciamos o frame frame = 0 para que a imagem a ser exibida seja a imagem inicial. Colocamos o estado em 0 STATE = 0, pois volta ao estado inicial. Como o barril foi destrudo, criamos um novo barril, nesse caso apenas sorteamos novas posies para ele barrilx=Rnd(50,750) e barrily=Rnd(20,200).
If ImagesCollide(tiro, px, py, 0, barril, barrilx, barrily, 0) STATE = 2 py = 500 TIROS_CERTOS = TIROS_CERTOS + 1 PONTOS = PONTOS + (205 - barrily) EndIf

Aqui est o ncleo principal dos eventos, a deteco da coliso. Veja que a posio da imagem tiro dada pelas variveis de controle da sua posio (tiro, px, py, 0 ..., pois ele est em movimento. Se a coliso foi detectada primeiro colocamos o estado do jogo para o estado de explodir o barril STATE = 2 e reiniciamos a posio do tiro py=500. Tambm contabilizamos os tiros certos TIROS_CERTOS=TIROS_CERTOS+1 e em seguida os pontos PONTOS=PONTOS+(205barrily). Veja que os pontos so dados por uma frmula onde quanto mais acima na tela estiver o barril, maior ser a pontuao.
If MouseHit(1) If STATE = 0 STATE = 1 TOTAL_TIROS = TOTAL_TIROS + 1 EndIf EndIf

Aqui disparamos o tiro. Para que ele seja disparado so necessrias 2 condies: a primeira que o boto esquerdo do mouse seja pressionado If MouseHit(1) e que o jogo esteja no estado inicial de espera If STATE = 0. Sendo essas condies vencidas, ento colocamos o tiro em movimento acionando o estado 1 STATE = 1 e contabilizamos mais um tiro disparado TOTAL_TIROS = TOTAL_TIROS + 1.
DrawImage barril, barrilx, barrily, frame DrawImage tiro, px, py

Nessas linhas exibimos as imagens.


Text 100, 0, "PONTOS: " + PONTOS Text 350, 0, "TOTAL DE TIROS: " + TOTAL_TIROS

E aqui as informaes do jogo. Restringindo o movimento Outra funcionalidade importante de um sistema de colises e restringir os movimentos de um personagem. Quando o personagem se choca com a parede ele deve parar de se mover, no pode atravessar a mesma. Isso parece simples de ser criado, seria s verificar a coliso e se estiver colidindo, bloquear o movimento... Mas no bem assim. Se fizssemos dessa forma o personagem jamais andaria novamente, ficaria colado na parede. A restrio deve ser feita de forma que ele seja impedido de andar para onde existe coliso. Agora parece complexo... Mas calma existe um algoritmo simples para implementar isso. Devemos ter duas variveis de posio x e y. Uma varivel marcar sempre a posio anterior do personagem a outra guarda a posio depois de ele se mover. Se houve coliso, dizemos que a posio atual igual a posio antes do movimento, assim a imagem fica parada na posio anterior. Se no existe coliso, ela se move normalmente. Veja a lgica: ultimapx = px ultimapy = py movepx() movepy() If colide() px = ultimapx py = ultimapy End if ExibirImagens() A primeira coisa a se fazer nessa lgica guardar uma cpia da posio do objeto antes de ele mover. ultimapx = px ultimapy = py depois disso podemos fazer os inputs de teclado e mover o mesmo. movepx() movepy() O passo seguinte verificar h uma coliso. If colide() E se colidiu, volta o mesmo sua posio antes de ser movido. px = ultimapx py = ultimapy Simples no mesmo? O exemplo abaixo mostra como isso feito na prtica. Exemplo 43

Graphics 800, 600 SetBuffer BackBuffer() laberinto = LoadImage("midia\laberinto.png") bola = LoadImage("midia\bola2.png") px = 400 py = 300 While Not KeyHit(1) ultimapx = px ultimapy = py If KeyDown(200) Then py = py - 2 If KeyDown(208) Then py = py + 2 If KeyDown(203) Then px = px - 2 If KeyDown(205) Then px = px + 2 If ImagesCollide(laberinto,150,50,0, bola,px,py,0) px = ultimapx py = ultimapy EndIf DrawImage laberinto, 150, 50 DrawImage bola, px, py Flip Cls Wend

tela, pois sempre a tela toda ser preenchida por esse comando. O parmetro de frame opcional, e deve ser usado para imagens animadas. Horizontal scrolling Horizontal scrolling a tcnica de rolagem do cenrio no eixo horizontal. Isso muito usando em jogos 2D de aventura como Mario ou Sonic, onde o personagem s se movimenta para frente ou para traz e os cenrios so grandes. No prximo exemplo, fazemos um Scrolling Horizontal a partir de tiles. Exemplo 45
Graphics 640,480,16 SetBuffer BackBuffer() tile=LoadImage("midia\tile.png") While Not KeyHit(1) x = x + 1 TileImage tile, 0 + x, 0 Flip Wend

SCROLLING A tcnica de scrolling nada mais do que criar um efeito de continuidade do cenrio por meio de rolagem e repetio. Podemos criar esse efeito por meio da repetio de uma imagem que seja o fundo do cenrio ou por meio de tiles que vo compor esse cenrio. Na maioria das engines e programas, a montagem da tela se d de forma manual, mas o Blitz3D possui o comando TileImage que faz esse trabalho duro pra voc de composio do fundo. Dessa forma voc s precisa se preocupar em fazer a rolagem. Veja abaixo um exemplo onde o Blitz3D cria um fundo de cenrio a partir de um tile de apenas 17 x 17. Exemplo 44
Graphics 640,480,16 SetBuffer BackBuffer() tile=LoadImage("midia\tile.png") While Not KeyHit(1) TileImage tile, 0, 0 Flip Wend

Mas o caso mais tpico de uso desse tipo de rolagem com cenrios como o do exemplo abaixo. Exemplo 46
Graphics 640,480,16 SetBuffer BackBuffer() tile=LoadImage("midia\tela.jpg") While Not KeyHit(1) x = x + 1 TileImage tile, 0 - x, 0 Flip Wend

Se adicionarmos uma imagem de um personagem ai fica muito bom o aspecto... Exemplo 47


Graphics 640,480,16 SetBuffer BackBuffer() tile = LoadImage("midia\tela.jpg") robo = LoadAnimImage("midia\robo2c.bmp", 50, 80, 0, 8) While Not KeyHit(1) contador = contador + 1 If contador = 5 contador = 0 frame = frame + 1 If frame = 8 Then frame = 0 EndIf fx = fx - 2 TileImage tile, fx, 0 DrawImage robo, 200, 325, frame Flip Cls Wend

Veja que apenas um comando preencheu a tela toda.


TileImage tile, 0, 0

Esse comando preenche toda a tela a partir da imagem passada como parmetro. Sua assinatura : TileImage imagem, posiox, posioy, frame As posies x e y no so de onde a exibio ser iniciada, mas de offset da imagem, isso , de encaixe, como elas se posicionam na

Vertical Scrolling A tcnica de Vertical Scrolling normalmente usada para criar jogos de nave ou de carros que se movimentam no sentido de baixo para cima da tela. Para criar esse efeito s

deixar a posio y de exibio do tile como dinmica. Veja o exemplo abaixo. Exemplo 48
Graphics 640,480,16 SetBuffer BackBuffer() tile = LoadImage("midia\tile.png") missil = LoadImage("midia\f15.bmp") MaskImage missil, 255, 255, 255 MoveMouse(320,400) While Not KeyHit(1) FY = FY + 2 TileImage tile, 0, FY px = MouseX() DrawImage missil, px, 350 Flip Cls Wend

DrawImage arvore, 20 + Fx, -50 + Fy DrawImage arvore, 550 + Fx, 200 + Fy DrawImage arvore, 100 + Fx, 400 + Fy Color 0,0,0 Text 180, 20, "USE TECLAS DIRECIONAIS PARA MOVER" Color 255, 0, 0 Text 181, 21, "USE TECLAS DIRECIONAIS PARA MOVER" Flip Cls Wend

Double Scrolling Para fazer um Double Scrolling basta colocar os dois parmetros de localizao do tile como dinmicos: Fx e Fy. Essa tcnica usada em jogos que possuem liberdade total de movimento e usam um tile nico como fundo bsico de cenrio. Exemplo 49
Graphics 640,480,16 SetBuffer BackBuffer() tile = LoadImage("midia\tile.png") MoveMouse(320,400) While Not KeyHit(1) If KeyDown(200) Then Fy = Fy + 1 If KeyDown(208) Then Fy = Fy - 1 If KeyDown(203) Then Fx = Fx + 1 If KeyDown(205) Then Fx = Fx - 1 TileImage tile, Fx, Fy Color 0,0,0 Text 180, 20, "USE TECLAS DIRECIONAIS PARA MOVER" Color 255, 0, 0 Text 181, 21, "USE TECLAS DIRECIONAIS PARA MOVER" Flip Cls Wend

Parallax Scrolling Por meio dessa tcnica conseguimos colocar efeito de perspectiva em um jogo 2D. No uma tcnica muito comum de ser vista em jogos, mas ela cria um efeito muito interessante, gerando um bom visual. Para fazer um Parallax Scrolling, devemos ter dois, ou mais, objetos de fundo se movendo em velocidades diferentes, gerando uma sensao de profundidade, de um estar em maior distncia que o outro. Para gerar esse efeito temos que ter um controle Fx para cada objeto de fundo de distncia diferente. Os mais distantes se movem em velocidade menor e os mais prximos em velocidade maior. No exemplo que vamos apresentar usamos o TileImage apenas para compor o fundo da imagem, por se a nica coisa que se repete por todo o cenrio. Os demais elementos foram exibidos por meio do comando DrawImage. Exemplo 51
Graphics 640,480,16 SetBuffer BackBuffer() fundo_parado = LoadAnimImage("midia\paralax.png", 50, 50, 0, 1) fundo_paralax1 = LoadImage("midia\paralax.png") Tile = LoadAnimImage("midia\tile2.png", 11, 11, 0, 9) MaskImage tile, 255, 255, 255 While Not KeyHit(1) If KeyDown(203) Then Fx# = Fx# + 1 If KeyDown(205) Then Fx# = Fx# - 1 ; FUNDO AZUL - esttico TileImage fundo_parado, 0, 0,0 ;MONTANHAS - MOVE 1 DrawImage fundo_paralax1, -400 + Fx#, 340 DrawImage fundo_paralax1, 0 + Fx#, 340 DrawImage fundo_paralax1, 400 + Fx#, 340 DrawImage fundo_paralax1, 800 + Fx#, 340 ;PISO - MOVE 4 For x = - 4000 To 4200 Step 11 px = x + (fx# * 4) If px > -11 And px < 801 DrawImage Tile, px, 440, 0 DrawImage Tile, px, 451, 8

Os demais elementos que iro compor o cenrio devero ser posicionados manualmente e ter sua posio de exibio ajustada por Fx e Fy. Veja, no exemplo abaixo, como compor e controlar objetos do cenrio. Exemplo 50
Graphics 640,480,16 SetBuffer BackBuffer() tile = LoadImage("midia\tile.png") arvore = LoadImage("midia\arvore.bmp") MoveMouse(320,400) While Not KeyHit(1) If KeyDown(200) Then Fy = Fy + 1 If KeyDown(208) Then Fy = Fy - 1 If KeyDown(203) Then Fx = Fx + 1 If KeyDown(205) Then Fx = Fx - 1 TileImage tile, Fx, Fy

DrawImage Tile, px, 462, 8 DrawImage Tile, px, 473, 8 EndIf Next ;VIGAS - MOVE 2 For x = - 1000 To 1200 Step 190 px = x + (fx# * 2) If px > -11 And px < 801 DrawImage Tile, px, 418, 7 DrawImage Tile, px, 429, 6 EndIf Next For x = - 1000 To 1200 Step 140 px = x + (fx# * 2) If px > -11 And px < 801 DrawImage Tile, px, 418, 7 DrawImage Tile, px, 429, 6 EndIf Next ;FLOR - MOVE 3 For x = - 2000 To 2200 Step 190 px = x + (fx# * 3) If px > -11 And px < 801 DrawImage Tile, px, 429, 4 EndIf Next ;ARBUSTO - MOVE 4 For x = - 2000 To 2200 Step 140 px = x + (fx# * 4) If px > -11 And px < 801 DrawImage Tile, px, 429, 5 EndIf Next Color 0,0,0 Text 180, 20, "USE TECLAS DIRECIONAIS PARA MOVER" Color 255, 0, 0 Text 181, 21, "USE TECLAS DIRECIONAIS PARA MOVER" Flip Cls Wend

relao ao FX. O piso, em primeiro plano, move a fx# * 4, isso , quatro vezes mais que as montanhas e possui a mesma velocidade do arbusto. J as flores, tm sua posio dada pela equao fx# * 3, assim ela trs vezes mais velos que as montanhas, mas mais lenta que o piso e o arbusto. No meio de tudo esto as pilastras, que se movem por fx# * 2, sendo o dobro da velocidade das montanhas e a metade da velocidade do piso em primeiro plano. Usamos tambm um sistema de seleo de exibio de imagem. Como nosso cenrio muito grande no devemos mandar o programa compor imagem que esto fora da rea de viso. Por isso verificamos se a imagem est localizada na rea do monitor antes de exibir:
If px > -11 And px < 801 DrawImage Tile, px, 429, 5 EndIf

Perceba que no existe praticamente nada de novo nesse programa. Todos os comandos e tcnicas j foram estudados; s uma combinao de tcnicas. Vejas essas linhas abaixo:
DrawImage DrawImage DrawImage DrawImage DrawImage DrawImage Tile, Tile, Tile, Tile, Tile, Tile, px, px, px, px, px, px, 440, 451, 418, 429, 429, 429, 0 8 7 6 4 5

Veja que todas as imagens tm uma posio x dinmica PX, e todos esses PX so dados por uma relao com FX que controlado pelo teclado.
px = x + (fx# * 4) px = x + (fx# * 3) px = x + (fx# * 2)

S o bloco de exibio das montanhas no possui essa frmula, pois ele usa o FX diretamente. Os demais so movimentados atravs de uma proporcionalidade em

6. DeskTroy O objetivo desse mdulo criar um jogo 2d completo. Vamos criar uma verso de breakout. A escolha desse jogo se d por ele possuir uma lgica simples, ai voc poder ter seu foco mais voltado para compreender a arquitetura do jogo, que o nosso objetivo. Por meio desse exerccio, iremos compreender como estruturar um jogo lgica e fisicamente; como dividir o cdigo fonte em mdulos e em arquivos com responsabilidades prprias; e o mais importante: como estruturar logicamente os controles e eventos de um jogo. Primeiro passo: requisitos funcionais O primeiro passo no desenvolvimento de um software fazer um levantamento de seus requisitos, isso , as caractersticas que o programa dever possuir. nesse momento que se d a contratao de um projeto de jogo. Decidimos se vivel ou no, e qual ser o custo da aplicao. Se ns estamos desenvolvendo um trabalho para um cliente, esse documento de requisitos dever servir como um contrato de trabalho onde so especificados o que dever ser desenvolvido e qual ser o custo disso. Abaixo temos uma lista no muito rigorosa para esse projeto. Projeto: DeskTroy

Objetivo: criar um jogo semelhante ao clssico Breakout. 1. O jogo consiste de quatro elementos fsicos: uma bolinha, um batedor, vrios blocos e paredes. 2. O jogador ter 3 vidas, ou trs bolas de chance. 3. Quando a bola passar da linha limite inferior da tela, o jogador perde uma vida(bola). 4. As partes superior e lateral da tela so protegidas pela parede, no havendo perda de bolas. 5. Na parte superior da tela existem vrios bloco que sero destrudos ou perdero vida ao se chocar com a bola. 6. Os blocos sero de trs tipos: vermelho, com 3 unidades de vida; azul, com 2 de vida e verde, com 1 de vida. 7. Cada vez que a bola se chocar com um bloco, esse perder uma unidade de vida. 8. Quando todos os blocos forem destrudos, passamos de fase. 9. Se perdermos as trs bolas, o jogo acaba. 10. Ao chocar com as paredes e com os blocos, a bola ter sua direo alterada, com um efeito de rebater de bola. 11. Ao se chocar com o meio do batedor, a bola tambm ser apenas rebatida. Se a bola se chocar com os pontos mais laterais do batedor, a bola ter seu sentido levemente alterando para o sentido da lateral que se chocou. 12. A pontuao se dar por sistema de combos. A primeira vez que a bola se chocar com um bloco render 1 ponto, nas vezes seguintes que se chocar, sem ter colidido com o batedor, os pontos sero aumentados progressivamente em uma unidade. Toda vez que a bola se chocar com o batedor, o combo ser reiniciado para 1 ponto. 13. O jogador controlar o batedor por meio do mouse, em seu eixo x. 14. Quando inicia-se uma partida, uma fase ou uma nova bola, a bola fica em estado de espera, acompanhando a posio do batedor, at que o jogador a libere ao clicar o boto esquerdo do mouse. 15. Se o jogador apertar o boto esc durante a partida, a partida ser encerrada e ir para a tela de menu. 16. No menu temos as opes de iniciar um jogo e sair da aplicao. 17. Quando iniciamos o programa, essa aplicao cair na tela de menu.

Segundo passo: requisitos de mdias Agora de nosso cliente j nos passou as caractersticas funcionais da aplicao, dever tambm nos passar os requisitos artsticos, o storyboard dessa aplicao. No caso, somos ns mesmos que estamos construindo a aplicao por nossa conta, portanto j sabemos o que vamos fazer e isso pode ser dispensvel. Se nossos requisitos artsticos forem elaborados por terceiros, tambm seria necessrio elaborar um storyboard para passar para o artista que vai criar as Midas. Terceiro passo: elaborao das mdia Antes de por as mos na massa, no software em si, devemos criar as mdias (ou pelo menos algumas delas se estamos desenvolvendo em um processo iterativo com vrios integrantes na equipe). Se o jogo desenvolvido para um cliente devero ser feitas validaes das mdias Abaixo temos as mdias para esse jogo: Som1.wav Som2.wav Som3.wav

OBS: as imagens no esto no tamanho original, foram ajustadas para dar melhor aspecto visual para o projeto.

Quarto passo: designer do projeto de software. Nesse momento fazemos diagramas UML para documentar a estrutura do software. Esses diagramas foram desenvolvidos originalmente para o projeto de software orientado a objetos, mas quem pode o mais, pode o menos, portanto eles servem para representar qualquer coisa, at uma receita de bolo, ou as suas tarefas cotidianas de compras. Como esse projeto muito simples, usaremos apenas o diagrama de classes. Isso vai ser muito importante para podermos projetar a estrutura do software de uma forma mais simples e rpida. No recomendo a ningum a tcnica de tirar um software da cabea direto para o cdigo sem ter um projeto antes, isso sempre gera muitos

problemas e acaba demorando 5 vezes mais fazer. Com um diagrama como o de classes fica muito fcil projetar como o software dever funcionar, como as peas se encaixam e voc ter em apenas uma pgina a representao de milhares de linhas de cdigo. Isso impossvel de conseguir com o cdigo fonte. Alm do mais com isso teremos uma planta de como ele funciona, nos orientado na hora de efetuar a sua implementao. Assim dificilmente ocorrero erros. O que um diagrama de classes mostra? Um diagrama de classes mostra a estrutura esttica de um software, como suas unidade so constitudas e como elas se relacionam. Classes so estruturas de software independentes que possuem em si dados e mtodos e os diagramas de classes mostram essas classes com as caractersticas de seus dados e mtodos e como eles se relacionam com outras classes. O Blitz3d no suporta classes, mas estamos desenvolvendo esse software com uma estrutura lgica semelhante de classes, onde dividimos o cdigo em arquivos, como se fossem classes, isso , os dados e os mtodos de um mesmo objeto esto em um s arquivo, por isso ele pode ser representado por esse diagrama. Veja a estrutura de representao de uma Classe:

nossos diagramas teremos apenas uma seta pontilhada, que representa dependncia de uma classe em relao outra. Essa dependncia normalmente significa que aquela classe est usando uma funo da outra e por isso depende dela. Isso muito importante para mapear relacionamentos entre os mdulos do projeto. Assim, nosso projeto para esse jogo fica com est abaixo:

Veja que acima temos o nome da classe, no nosso caso, o nome do arquivo. Logo a baixo, no segundo compartimento, temos as variveis da classe, em nosso caso, as variveis do arquivo. E por ltimo, em baixo as funes (mtodos) da classe, em nosso caso, as funes do arquivo. Dependncias No diagrama temos vrios tipos de relaes entre uma classe e outra. Como o Blitz3D no suporta essas relaes por no suportar POO (programao orientada a objetos), em

Tipos Veja que os dados e mtodos possuem qualificadores como int, void, boolean, String. Eles se referem a qual o tipo dos dados ou a qual o tipo de valor que uma funo aceita ou ento retorna. Perceba que para sons e imagens deixei esses qualificadores de tipos como int. Em diagrama de classes de uma linguagem orientadas a objetos normalmente isso seria um objeto, mas como no Blitz3d no possumos objetos e ele cria ponteiros internos para essas mdias que so

referenciados por uma varivel do tipo int, achamos melhor deixa seus tipos como int. Classe (arquivo) Game. Veja que esse o nosso arquivo principal que controla todos os demais. Isso fcil de perceber pois saem setas dele para todos os outros. Isso significa que ele usa funes de todos. Veja que ela possui variveis internas para controlar Vidas, Scores e Fase e ela controla a Fsica, Lgica, Colises e Desenho do programa. Dividindo por objetos e responsabilidades A melhor maneira de projetar um software por responsabilidades e objetos. Cada tipo de objeto do jogo dever ser uma classe assim como entidades lgicas com responsabilidades especficas. Objetos Os objetos fsicos que viraram classes so: bola, bloco, parede e batedor. Os dados desses objetos, assim como as suas funes de controle devem estar em um arquivo para cada um deles. Responsabilidades Entidades como Game, menu, Fase1, etc, no so coisas fsicas, objetos em si, mas denotam relaes complexas com lgica e responsabilidades prprias, por isso devem ser organizadas em um arquivo prprio para cada um. Por exemplo, no controle de fase, cada fase possui uma estrutura de criao, de controle, de descarregar, de verificao, etc, por isso, como existem diversas responsabilidades do mesmo tipo, criamos um arquivo para cada fase onde temos uma concentrao lgica e fsica dos mesmos processos. Isso facilita muito, pois Sabemos onde cada coisa est e o que cada coisa faz. Fica mais fcil desenvolver, alterar e corrigir eventuais erros. Quinto Passo: implementao. A nossa penltima fase a de implementao da aplicao, a digitao do cdigo do Blitz3D segundo o projeto desenvolvido pelo diagrama UML. O ideal ter uma cpia desse diagrama em mo, pois ele ser o seu mapa, seu guia de bordo, a planta a partir da qual voc constri seu software. Arquivo Creditos.bb Perceba que a classe que representa esse arquivo no possui dados, mas apenas dois mtodos:
Abrir():void Sair():void

O mtodo Abrir() ser usado para iniciar a parte visual da aplicao, vai apresentar o projeto. Dever mostrar na tela, por 5 segundos, a mensagem Cusos UDCO e Blitz3. O mtodo Sair() o que ir encerrar a aplicao, dando retorno ao Windows. Ele exibir os crditos do jogo, isso sua autoria: nesse projeto o meu nome em outros o seu ou o de sua empresa. Vamos ao cdigo fonte explicado. Veja o cdigo da funo de apresentao do programa.
Function Creditos_Abrir() tela = LoadImage("midia\udco.jpg") t1 = MilliSecs() While(t2-t1 < 5000) DrawImage tela, 150, 200 ; imagem de 500x400 t2 = MilliSecs() Flip Cls Wend End Function

Veja que a funo se inicia com o mesmo nome do arquivo Creditos, assim sabemos onde ela est fisicamente.
tela = LoadImage("midia\udco.jpg")

Carregamos a imagem da apresentao, mas isso no pode ser considerado um dado, por ser uma varivel voltil, ser destruda no final da funo.
t1 = MilliSecs()

Essa imagem dever ser exibida por 5 segundos, portanto pegamos o tempo inicial para calcular esses 5 segundos. O comando Millisecs() d o tempo do sistema em milsimos de segundos.
While(t2-t1 < 5000)

Faremos o sistema de tempo por meio de um loop. A condio : enquanto tempo 2 T2 menos tempo 1 T1 for menor que 5.000, isso , cinco segundos, pois a funo retorna o tempo em milsimos de segundos.
DrawImage tela, 150, 200 ; imagem de 500x400

Enquanto no der os 5.000 milsimos de segundos, exibimos a imagem na tela.


t2 = MilliSecs()

Atualizamos o tempo 2 a todo momento para ver se chegou aos 5 segundos. Vamos agora ao cdigo da segunda funo.
Function Creditos_Sair() tela = LoadImage("midia\credito.jpg") t1 = MilliSecs() While(t2-t1 < 5000) DrawImage tela, 150, 270 ; imagem de 500x60 t2 = MilliSecs() Flip

Cls Wend End End Function

While e esse loop ser controlado pela chave iniciar, que se inicia com o valor 0.
;detectando a posio do mouse mx = MouseX() my = MouseY()

Veja que essa funo praticamente igual a anterior, exceto nesse trecho:
Wend End

Depois de vencidos os 5 segundos essa funo no retorna o controle para a aplicao que a invoca, ela encerra a aplicao. Isso se d por se tratar da funo de sair. CODIGO COMPLETO DE CREDITOS.BB
Function Creditos_Abrir() tela = LoadImage("midia\udco.jpg") t1 = MilliSecs() While(t2-t1 < 5000) DrawImage tela, 150, 200 ; imagem de 500x400 t2 = MilliSecs() Flip Cls Wend End Function Function Creditos_Sair() tela = LoadImage("midia\credito.jpg") t1 = MilliSecs() While(t2-t1 < 5000) DrawImage tela, 150, 270 ; imagem de 500x60 t2 = MilliSecs() Flip Cls Wend End End Function

Estamos capturando a posio do mouse para exibirmos o cursor do mouse no local correto e detectar sua posio para o controle de botes do menu.
;exibindo DrawImage DrawImage DrawImage imagens menu_IMGlogo, 150, 200 menu_IMGsair, 165, 300 menu_IMGjogar,440, 300

Aqui estamos exibindo as imagens do logo do jogo e dos dois botes.


If mx > 165 And mx < 365 If my > 300 And my < 367 Rect 165,300, 200, 65, 0 If MouseHit(1) Then Creditos_Sair() EndIf EndIf

Arquivo Menu.bb Esse arquivo de cdigo responsvel pela exibio e controle do menu. Vamos a sua explicao.
Global menu_IMGlogo Global menu_IMGsair Global menu_IMGjogar Global menu_IMGmouse menu_IMGlogo = LoadImage("midia\logo.jpg") menu_IMGsair = LoadImage("midia\btn_sair.jpg") menu_IMGjogar = LoadImage("midia\btn_jogar.jpg") menu_IMGmouse = LoadImage("midia\mouse.png")

Esse trecho de cdigo controla o primeiro boto, o boto sair. A primeira coisa que devemos fazer para isso verificar se o cursor do mouse est sobre o boto. O primeiro passo verificarmos a posio x do mouse, se ela est sobre o boto sair If mx > 165 And mx < 365 o segundo passo verificar se a posio y dele tambm coincide If my > 300 And my < 367. Se as duas verificaes forem verdadeiras, exibimos um retngulo em volta do boto para dar a sensao de foco no boto Rect 165, 300, 200, 65, 0 e verificamos se o boto esquerdo do mouse apertado If MouseHit(1). Caso isso seja verdadeiro, invocamos a funo para encerrar a aplicao Creditos_Sair().
If mx > 440 And mx < 640 If my > 300 And my < 367 Rect 440,300, 200, 65, 0 If MouseHit(1) Then iniciar = 1 EndIf EndIf

Veja que estamos declarando 4 variveis globais para receber imagens. Fizemos isso pelo fato de elas serem acessadas dentro de funes, assim s com a definio de global elas seriam acessveis.
Function menu_exibir() iniciar = 0 While Not (iniciar)

A segunda funo de controle de boto tem a mesma estrutura da anterior. Mas no caso desse boto, caso ele seja pressionado, vamos mudar o estado da chave de 0 para 1. Isso faz com que o loop do menu seja encerrado e a execuo do cdigo siga o fluxo adiante.
DrawImage menu_IMGmouse, mx, my

Essa nossa funo de exibio do menu. Veja que ela ser implementada por um loop

Ainda dentro do loop, esse comando exibe o cursor do mouse. Deixamos ele por ltimo pelo fato de o mouse ter que ser exibido acima de qualquer outra imagem e a ordem de empilhamento depende da seqncia na qual ordenamos as exibies de imagens.
Fase1_carregar()

Veja que no final da funo carregamos a Fase 1 do jogo. por isso que em nosso diagrama, temos uma dependncia de Menu em relao a Fase1. CODIGO COMPLETO DE MENU.BB
Global menu_IMGlogo Global menu_IMGsair Global menu_IMGjogar Global menu_IMGmouse menu_IMGlogo = LoadImage("midia\logo.jpg") menu_IMGsair = LoadImage("midia\btn_sair.jpg") menu_IMGjogar = LoadImage("midia\btn_jogar.jpg") menu_IMGmouse = LoadImage("midia\mouse.png") Function menu_exibir() iniciar = 0 While Not (iniciar) ;detectando a posio do mouse mx = MouseX() my = MouseY() ;exibindo imagens DrawImage menu_IMGlogo, 150, 200 DrawImage menu_IMGsair, 165, 300 DrawImage menu_IMGjogar,440, 300 ;verificandos se est sobre os botes ; e se clicou neles If mx > 165 And mx < 365 If my > 300 And my < 367 Rect 165,300, 200, 65, 0 If MouseHit(1) Then Creditos_Sair() EndIf EndIf If mx > 440 And mx < 640 If my > 300 And my < 367 Rect 440,300, 200, 65, 0 If MouseHit(1) Then iniciar = 1 EndIf EndIf ; exibir o mouse por ultimo DrawImage menu_IMGmouse, mx, my Flip Cls Wend Fase1_carregar() End Function

Batedor\image = LoadImage("midia\batedor.png") Batedor\px = 350 Batedor\py = 520

Acima estamos criando uma instncia da estrutura do Type. Veja que a declaramos como Global, pois ser acessada de dentro de funes. Estamos tambm carregando a imagem, e definindo a posio inicial dele.
Function Batedor_draw() DrawImage Batedor\image, Batedor\px, Batedor\py End Function

Essa funo exibe a imagem do batedor na tela. Veja que usamos os dados internos da instncia do Type para exibir a imagem.
Function Batedor_colide(obj, px, py) If ImagesCollide(Batedor\image, Batedor\px, Batedor\py, 0, obj, px, py, 0) If (PX - Batedor\px < 20) Then Return 1 If (PX - Batedor\px > 60) Then Return 3 Return 2 EndIf Return 0 End Function

Arquivo Batedor.bb Esse arquivo de cdigo responsvel pela exibio e controle do menu. Vamos a sua explicao.
Type TBATEDOR Field image Field px Field py End Type

Essa funo responsvel pelas colises do batedor. Embora ele s ir colidir com a bola, criamos uma funo genrica que aceita verificar se ocorreram colises com qualquer imagem passada como parmetro. Fizemos assim por dois motivos: evitar aumento de dependncia no cdigo e por motivo didtico, pois isso deixa voc mais habituado com programao genrica. Veja que se houver coliso essa funo retornar um dos seguintes valores: 1, 2 e 3. Se no houver coliso, ento retornar o valor 0. O valor retornado ser 1 se a coliso se der na borda esquerda do batedor e 3 se ocorrer na borda direita. Se colidir no meio dele ir retornar 2. por meio desses valores retornados que a bola ir mudar ou no sua rota, e saber para onde dever se deslocar.
Function Batedor_Mover(px, py) Batedor\px = px If Batedor\px < 50 Then Batedor\px = 50 If Batedor\px > 650 Then Batedor\px = 650 End Function

O batedor uma entidade fsica do jogo, por isso criamos um Type para conter suas propriedades. O campo image conter a imagem do batedor. Os campos px e py a sua posio na tela.
Global Batedor.TBATEDOR = New TBATEDOR

Nossa ltima funo desse arquivo responsvel por controlar o movimento do batedor. Ela recebe dois parmetros que sero passados pela posio atual do mouse (a posio x) e por um valor fixo, no caso do eixo y. Veja tambm que colocamos um sistema para impedir que o batedor atravesse a parede de tijolos, limitando sua posio

mxima e mnima. Assim ele dever estar entre 50 e 650, pois as paredes tem 50 pixels de largura e so exibidas a partir do ponto 0 e o batedor tem 100 de comprimento. CODIGO COMPLETO DE BATEDOR.BB
Type TBATEDOR Field image Field px Field py End Type Global Batedor.TBATEDOR = New TBATEDOR Batedor\image = LoadImage("midia\batedor.png") Batedor\px = 350 Batedor\py = 520 Function Batedor_draw() DrawImage Batedor\image, Batedor\px, Batedor\py End Function Function Batedor_colide(obj, px, py) If ImagesCollide(Batedor\image, Batedor\px, Batedor\py, 0, obj, px, py, 0) If (PX - Batedor\px < 20) Then Return 1 If (PX - Batedor\px > 60) Then Return 3 Return 2 EndIf Return 0 End Function Function Batedor_Mover(px, py) Batedor\px = px If Batedor\px < 50 Then Batedor\px = 50 If Batedor\px > 650 Then Batedor\px = 650 End Function

identidade servir para diferenciar os efeitos de colises com a bola, pois as paredes da esquerda produzem efeitos diferentes das paredes da direita e tambm das de cima. Por isso a funo de colises dever retornar valores diferentes de acordo com o tipo da parede. Isso poderia ser feito matematicamente tambm, mas preferimos essa opo mais simples.
Function PAREDE_Delete() For This.TPAREDE = Each TPAREDE Delete This Next End Function

Essa nossa funo destrutora de objetos, ela ser invocada ao final de cada fase para destruir os objetos da parede. Como na funo construtora no declaramos os objetos como Globais, no podemos invocar os objetos pelo prprio nome para destru-los por isso, criamos um novo ndice This para todos os objetos do tipo TPAREDE que esto em uma lista oculta do Blitz, e assim conseguimos acessar os objetos declarados anteriormente. Assim deletamos todos eles.
Function Parede_draw() For this.TPAREDE = Each TPAREDE DrawImage PAREDE_IMG, this\px, this\py Next End Function

Arquivo Parede.bb Esse arquivo responsvel pelo gerenciamento dos objetos da parede do jogo. Veja abaixo a explicao de como ele foi elaborado.
Global PAREDE_IMG PAREDE_IMG = LoadImage("midia\parede.bmp")

Esse mtodo vai exibir todos os objetos do tipo TPAREDE na tela, veja que ele usa o mesmo sistema de acesso da funo anterior. Ns usamos this por ser algo j consagrado em programao, mas o nome aqui poderia ser qualquer um, pois qualquer objeto de um tipo pode ter acesso lista daquele tipo por meio da estrutura For-Each.
Function Parede_Colide(obj, px, py) For this.TPAREDE = Each TPAREDE If ImagesCollide(PAREDE_IMG, this\px, this\py, 0, obj, px, py, 0) If this\id$ = "esquerda" Then Return 1 If this\id$ = "acima" Then Return 2 If this\id$ = "direita" Then Return 3 EndIf Next Return 0 End Function

Como teremos vrios objetos parede, optamos por deixar a imagem numa varivel a parte, para no criarmos vrias cpias da imagem de forma desnecessria.
Type TPAREDE Field id$ Field px Field py End Type

Aqui temos o prottipo das entidades que formaro a parede.


Function PAREDE_New(id$, px, py) PAREDE.TPAREDE = New TPAREDE PAREDE\id$ = id$ PAREDE\px = px PAREDE\py = py End Function

Nossa primeira funo uma construtora de objetos. Veja que ela recebe uma identidade e as posies x e y do bloco de tijolos. A

Por fim, nossa funo de colises. Como as demais, ela recebe uma imagem e suas posies x e y como parmetros, isso , ela foi construda de forma genrica. Tambm usamos a estrutura For-Each para acessar os dados dos objetos do tipo TPAREDE. Perceba que usamos a Id$ de cada objeto para retornar um valor por meio do comando Return. Esse valor retornado que determinar para onde a bola vai rebater.

Se no colidiu com nenhum objeto, retorna 0. CODIGO COMPLETO DE PAREDE.BB


Global PAREDE_IMG PAREDE_IMG = LoadImage("midia\parede.bmp") Type TPAREDE Field id$ Field px Field py End Type Function PAREDE_New(id$, px, py) PAREDE.TPAREDE = New TPAREDE PAREDE\id$ = id$ PAREDE\px = px PAREDE\py = py End Function Function PAREDE_Delete() For this.TPAREDE = Each TPAREDE Delete This Next End Function Function Parede_draw() For this.TPAREDE = Each TPAREDE DrawImage PAREDE_IMG, this\px, this\py Next End Function Function Parede_Colide(obj, px, py) For this.TPAREDE = Each TPAREDE If ImagesCollide(PAREDE_IMG, this\px, this\py, 0, obj, px, py, 0) If this\id$ = "esquerda" Then Return 1 If this\id$ = "acima" Then Return 2 If this\id$ = "direita" Then Return 3 EndIf Next Return 0 End Function

Function Bloco_New(vida, px, py) Bloco.TBLOCO = New TBLOCO Bloco\vida = vida Bloco\px = px Bloco\py = py End Function

Essa nossa funo construtora, criadora de instncias de blocos. Veja que devemos passar os dados de vida, posio x e posio y para criar um bloco.
Function Bloco_Delete() For this.TBLOCO = Each TBLOCO Delete This Next End Function

A funo destrutora semelhante do arquivo anterior, afinal tambm usamos a mesma arquitetura nesse arquivo.
Function Bloco_Existe() For this.TBLOCO = Each TBLOCO If this\vida > 0 Return 1 EndIf Next End Function

Arquivo Bloco.bb Esse arquivo controla os blocos coloridos da tela. Eles que so o alvo do jogo. Veja abaixo a explicao de como esse arquivo foi elaborado.
Global Bloco_IMG1 Global Bloco_IMG2 Global Bloco_IMG3 Bloco_IMG1 = LoadImage("midia\verde.bmp") Bloco_IMG2 = LoadImage("midia\azul.bmp") Bloco_IMG3 = LoadImage("midia\vermelho.bmp")

Essa funo tem a finalidade de verificar o fim da fase. Ela faz isso passando por todos os blocos existentes em busca de algum que possua uma vida maior que o valor zero, isso , algum bloco ativo If this\vida > 0. Ao encontrar o primeiro ela encerra sua execuo retornando o valor 1 Return 1. Se a funo passar por todos os elementos e no encontrar nenhum com vida maior que zero, no vai retornar valor algum, o que boleanamente significa 0, ou falso, e indica que a fase no est ativa.
Function Bloco_draw() For this.TBLOCO = Each TBLOCO If this\vida = 1 Then DrawImage Bloco_IMG1, this\px, this\py If this\vida = 2 Then DrawImage Bloco_IMG2, this\px, this\py If this\vida = 3 Then DrawImage Bloco_IMG3, this\px, this\py Next End Function

Estamos construindo variveis parte para armazenar as imagens. Assim no teremos vrias cpias desse dado.
Type TBLOCO Field vida Field px Field py End Type

Essa nossa funo de desenho, onde exibe cada imagem dependendo da vida de cada bloco. Se no tem vida, no exibe nada.
Function Bloco_colide(obj, px, py) For this.TBLOCO = Each TBLOCO If this\vida > 0 If ImagesCollide(Bloco_IMG1, this\px, this\py, 0, obj, px, py, 0) this\vida = this\vida - 1 Return 1 EndIf EndIf Next Return 0 End Function

Esse o nosso prottipo dos blocos. Possui um campo de vida, um da posio x e um para a posio y. No necessitamos colocar uma imagem para eles, pois a imagem ser definida pela vida, pois para cada vitalidade existe uma imagem.

Por fim a funo de colises. O teste de coliso s ocorre se a vida do bloco maior que 0 If this\vida > 0, isso , se o bloco est ativo, sendo exibido. Ao colidir, temos que tirar um ponto de vida do bloco this\vida = this\vida - 1 e devemos informar a quem invocou a funo que houve uma coliso Return 1. Caso no acontea uma coliso, retornamos o valor 0 Return 0. CODIGO COMPLETO DE BLOCO.BB
Global Bloco_IMG1 Global Bloco_IMG2 Global Bloco_IMG3 Bloco_IMG1 = LoadImage("midia\verde.bmp") Bloco_IMG2 = LoadImage("midia\azul.bmp") Bloco_IMG3 = LoadImage("midia\vermelho.bmp") Type TBLOCO Field vida Field px Field py End Type Function Bloco_New(vida, px, py) Bloco.TBLOCO = New TBLOCO Bloco\vida = vida Bloco\px = px Bloco\py = py End Function Function Bloco_Delete() For this.TBLOCO = Each TBLOCO Delete This Next End Function Function Bloco_Existe() For this.TBLOCO = Each TBLOCO If this\vida > 0 Return 1 EndIf Next End Function Function Bloco_draw() For this.TBLOCO = Each TBLOCO If this\vida = 1 Then DrawImage Bloco_IMG1, this\px, this\py If this\vida = 2 Then DrawImage Bloco_IMG2, this\px, this\py If this\vida = 3 Then DrawImage Bloco_IMG3, this\px, this\py Next End Function Function Bloco_colide(obj, px, py) For this.TBLOCO = Each TBLOCO If this\vida > 0 If ImagesCollide(Bloco_IMG1, this\px, this\py, 0, obj, px, py, 0) this\vida = this\vida - 1 Return 1 EndIf EndIf Next Return 0 End Function

Vamos fazer um estudo do arquivo de dados responsvel pelo controle da bola. Esse um dos mais complexos do projeto e merece especial ateno. Ele tem relaes especiais de dependncia, pois usa vrios mtodos de outros arquivos para implementar o sistema de colises e a dinmica do jogo.
Type TBOLA Field imagem Field px Field py Field vx Field vy End Type

O prottipo para a bola possui campos para imagem, posio x e y da bola e velocidades x e y. As velocidades se devem ao fato de que a bola no ser controlada pelo jogador, mas sua movimentao depende de um sistema de movimentao baseado em fsica vetorial.
Global Bola.TBOLA = New TBOLA Bola\imagem = LoadImage("midia\bola.png") Bola\px = 400 Bola\py = 520 Bola\vx = 0 Bola\vy = 5

Nessas linhas estamos instanciando o nosso objeto Bola e definido os seus valores iniciais padro.
Function Bola_fisica() Bola\px = Bola\px + Bola\vx Bola\py = Bola\py + Bola\vy End Function

Essa a nossa funo de fsica. O que ela faz calcular a nova posio da bola de acordo com a velocidade x e y dela. A nova posio igual posio atual mais a velocidade.
Function Bola_colide() ;--------------------COLISOES COM PAREDE ----------------------------tipo = Parede_Colide(Bola\imagem, Bola\px, Bola\py)

Aqui est o inicio de nossa grande funo de colises. A primeira verificao se est colidindo com a parede. Veja que invoca a funo de colises do arquivo parede e passa a ela como parmetro os dados da bola: imagem, posio x e posio y. Veja que essa invocao ter seu resultado guardado na varivel tipo que ir possuir qual o tipo de parede que colidiu.
; SE BATEU NA PAREDE DA ESQUERDA If tipo = 1 ; garantindo que vai para a direita Bola\vX = Abs(Bola\vX) EndIf

Arquivo Bola.bb

Se o valor retornado pela funo de coliso com parede 1 significa que a bola colidiu com a parede esquerda. Nesse caso vamos fazer com que a velocidade x da bola seja rebatida, isso , fique positiva. Para isso usamos a funo ABS() que retorna o valor absoluto de um nmero, isso seu estado positivo, quer seja ele positivou ou negativo. Assim, se a bola se chocou com a parede esquerda sinal que a sua velocidade x era negativa, agora ela se torna positiva, invertendo o seu sentido de movimento.
; SE BATEU NA PAREDE DE CIMA If tipo = 2 ; garantindo que vai para baixo Bola\vy = Abs(Bola\vy) EndIf

extremidade esquerda, causando um efeito de deslocamento de velocidade para esse lado. Como faremos um deslocamento de velocidade para a esquerda, temos que tornar a velocidade x uma unidade menor.
Bola\vx = Bola\vx 1

Mas essa velocidade lateral tem um limite, no poder passar de (-4), por isso fazemos os ajuste abaixo:
If Bola\vx < -4 Then Bola\vx = -4

Como nosso calculo de velocidade se baseia em vetor e esse possui o valor 5, podemos achar a velocidade y por meio da velocidade x:
Bola\vy = 5 - Abs(Bola\vx)

Se o valor retornado 2, a bola se chocou com a parede superior, ento devemos garantir que sua velocidade y seja positiva. Novamente usamos ABS().
; SE BATEU NA PAREDE DA DIRETA If tipo = 3 ; garantindo que vai para a esquerda Bola\vX = Abs(Bola\vX) * (-1) EndIf

Como a bola se chocou com o batedor, a partir de agora ela dever ir para cima, por isso temos que garantir que sua velocidade negativa, assim usamos a funo ABS abaixo.
Bola\vy = Abs(Bola\vy) * (-1)

O nosso sistema de pontos por combos e toda as vezes que a bola bate no batedor, reiniciamos os combos acumulados.
game\combo = 0

Se o choque se deu com a parede da direita, a velocidade x da bola ter que passar a ser negativa. Para isso primeiro aplicamos o ABS a velocidade atual garantindo que ela se se torne positiva, depois multiplicamos esse valor por (-1) para que ele se torne negativo.
;------------------------COLISOES COM BATEDOR-------------------------tipo = Batedor_colide(Bola\imagem, Bola\px, Bola\py)

O trecho a seguir executado caso a coliso se d na parte central do batedor.


;se bateu ao centro do batedor If tipo = 2 Bola\vy = Abs(Bola\vy) * (-1) game\combo = 0 EndIf

O que fazemos ento garantir que a bolinha v para cima e reiniciar os combos.
;se bateu a direita do batedor If tipo = 3 ;calcula fora lateral Bola\vx = Bola\vx + 1 ;limita a velocidade If Bola\vx > 4 Then Bola\vx = 4 ;calcula a fora para cima por vetor Bola\vy = 5 - Abs(Bola\vx) ;garante que vai para cima Bola\vy = Abs(Bola\vy) * (-1) game\combo = 0 EndIf

A partir do presente momento passamos a verificas as colises com o batedor. Veja que invocamos a funo de colises desse objeto e passamos para ele a imagem e os dados posicionais da bolinha.
If tipo > 0 Then PlaySound game\som_batedor

Caso ocorra esse tipo de coliso, ento iremos executar um efeito sonoro para criar um ambiente mais realista de jogo.
;se bateu a esquerda do batedor If tipo = 1 ;calcula fora lateral Bola\vx = Bola\vx - 1 ;limita a velocidade If Bola\vx < -4 Then Bola\vx = -4 ;calcula a fora para cima por vetor Bola\vy = 5 - Abs(Bola\vx) ;garante que vai para cima Bola\vy = Abs(Bola\vy) * (-1) game\combo = 0 EndIf

O cdigo acima executado caso haja uma coliso com a parte lateral do batedor. O efeito disso desviar a velocidade da bola um ponto mais direita, isso , aumentar a velocidade x em uma unidade.
Bola\vx = Bola\vx + 1

Devemos garantir que a velocidade lateral dela no ultrapasse 4 unidades.


If Bola\vx > 4 Then Bola\vx = 4

Esse bloco de cdigo executado se a coliso com o batedor se deu em suas

Da ento recalculamos a velocidade y da bolinha baseado no vetor 5.


Bola\vy = 5 - Abs(Bola\vx)

E garantimos que a velocidade y seja negativa e a bolinha v para cima.


Bola\vy = Abs(Bola\vy) * (-1)

Por ltimo as colises com os blocos:


; COLISOES COM BLOCOS If Bloco_colide(Bola\imagem, Bola\px, Bola\py)

Como voc se lembra, essa funo s retorna um tipo de dado, se colidiu ou no.
PlaySound game\som_bloco

Caso tenha havido a coliso, executamos um efeito sonoro.


;inverte velocidade vertical Bola\vy = Bola\vy * (-1)

Invertemos a velocidade y da bola. Isso necessrio por no sabermos se ela vai bater na parte superior ou inferior, pois no implementamos um sistema matemtico de deteco como para o batedor.
game\combo = game\combo + 1 game\scores = game\scores + game\combo

Atualizamos os combos e contabilizamos os novos pontos. A prxima funo responsvel por verificar se a bolinha caiu fora da tela, isso , passou pelo batedor e chegou parte inferior da tela.
Function Bola_morreu() If bola\py > 600 Then Return 1 End Function

Caso isso seja verdadeiro, retornar o valor 1.


Function Bola_reiniciar() Bola\px = 400 Bola\py = 520 Bola\vx = 0 Bola\vy = 5 End Function

Criamos essa funo apenas para reiniciar os valores da bola. Isso ser muito til quando perdemos uma bolinha e a nova deve ser colocada na posio inicial ou quando mudamos de fase.
Function Bola_draw() DrawImage Bola\imagem, Bola\px, Bola\py End Function

Nossa ultima funo responsvel por exibir a imagem do batedor. CODIGO COMPLETO DE BOLA.BB
Type TBOLA Field imagem Field px Field py Field vx Field vy End Type Global Bola.TBOLA = New TBOLA Bola\imagem = LoadImage("midia\bola.png") Bola\px = 400 Bola\py = 520 Bola\vx = 0 Bola\vy = 5

Function Bola_fisica() Bola\px = Bola\px + Bola\vx Bola\py = Bola\py + Bola\vy End Function Function Bola_colide() ;--------------------COLISOES COM PAREDE ----------------------------tipo = Parede_Colide(Bola\imagem, Bola\px, Bola\py) ; SE BATEU NA PAREDE DA ESQUERDA If tipo = 1 ; garantindo que vai para a direita Bola\vX = Abs(Bola\vX) EndIf ; SE BATEU NA PAREDE DE CIMA If tipo = 2 ; garantindo que vai para baixo Bola\vy = Abs(Bola\vy) EndIf ; SE BATEU NA PAREDE DA DIRETA If tipo = 3 ; garantindo que vai para a esquerda Bola\vX = Abs(Bola\vX) * (-1) EndIf ;------------------------COLISOES COM BATEDOR-------------------------tipo = Batedor_colide(Bola\imagem, Bola\px, Bola\py) If tipo > 0 Then PlaySound game\som_batedor ;se bateu a esquerda do batedor If tipo = 1 ;calcula fora lateral Bola\vx = Bola\vx - 1 ;limita a velocidade If Bola\vx < -4 Then Bola\vx = -4 ;calcula a fora para cima por vetor Bola\vy = 5 - Abs(Bola\vx) ;garante que vai para cima Bola\vy = Abs(Bola\vy) * (-1) game\combo = 0 EndIf ;se bateu ao centro do batedor If tipo = 2 Bola\vy = Abs(Bola\vy) * (-1) game\combo = 0 EndIf ;se bateu a direita do batedor If tipo = 3 ;calcula fora lateral Bola\vx = Bola\vx + 1 ;limita a velocidade If Bola\vx > 4 Then Bola\vx = 4 ;calcula a fora para cima por vetor Bola\vy = 5 - Abs(Bola\vx) ;garante que vai para cima Bola\vy = Abs(Bola\vy) * (-1) game\combo = 0 EndIf ; COLISOES COM BLOCOS If Bloco_colide(Bola\imagem, Bola\px, Bola\py) PlaySound game\som_bloco ;inverte velocidade vertical Bola\vy = Bola\vy * (-1) game\combo = game\combo + 1 game\scores = game\scores + game\combo

EndIf End Function Function Bola_morreu() If bola\py > 600 Then Return 1 End Function Function Bola_reiniciar() Bola\px = 400 Bola\py = 520 Bola\vx = 0 Bola\vy = 5 End Function Function Bola_draw() DrawImage Bola\imagem, Bola\px, Bola\py End Function

Por fim a funo de verificao se a fase ainda possui blocos ativos, que na verdade um re-direcionamento para a funo Bloco_Existe(). CODIGO COMPLETO DE FASE1.BB
Function Fase1_carregar() ;----------paredes----------;DE CIMA Parede_New("acima", 0, 0) Parede_New("acima", 50, 0) Parede_New("acima", 100, 0) Parede_New("acima", 150, 0) Parede_New("acima", 200, 0) Parede_New("acima", 250, 0) Parede_New("acima", 300, 0) Parede_New("acima", 350, 0) Parede_New("acima", 400, 0) Parede_New("acima", 450, 0) Parede_New("acima", 500, 0) Parede_New("acima", 550, 0) Parede_New("acima", 600, 0) Parede_New("acima", 650, 0) Parede_New("acima", 700, 0) Parede_New("acima", 750, 0) ;ESQUERDA Parede_New("esquerda", 0, 0) Parede_New("esquerda", 0, 43) Parede_New("esquerda", 0, 86) Parede_New("esquerda", 0, 129) Parede_New("esquerda", 0, 172) Parede_New("esquerda", 0, 215) Parede_New("esquerda", 0, 258) Parede_New("esquerda", 0, 301) Parede_New("esquerda", 0, 344) Parede_New("esquerda", 0, 387) Parede_New("esquerda", 0, 430) Parede_New("esquerda", 0, 473) Parede_New("esquerda", 0, 516) ;ESQUERDA Parede_New("direita", 750, 0) Parede_New("direita", 750, 43) Parede_New("direita", 750, 86) Parede_New("direita", 750, 129) Parede_New("direita", 750, 172) Parede_New("direita", 750, 215) Parede_New("direita", 750, 258) Parede_New("direita", 750, 301) Parede_New("direita", 750, 344) Parede_New("direita", 750, 387) Parede_New("direita", 750, 430) Parede_New("direita", 750, 473) Parede_New("direita", 750, 516) ;---------------blocos----------Bloco_New(3, 110, 100) Bloco_New(3, 175, 100) Bloco_New(3, 240, 100) Bloco_New(3, 305, 100) Bloco_New(3, 370, 100) Bloco_New(3, 435, 100) Bloco_New(3, 500, 100) Bloco_New(3, 565, 100) Bloco_New(3, 630, 100) Bloco_New(3, 110, 125) Bloco_New(1, 175, 125) Bloco_New(1, 240, 125) Bloco_New(1, 305, 125)

Arquivo Fase1.bb Esse arquivo responsvel pelo carregamento da fase 1 e por seu descarregamento quando ela acabar. Ela tambm prov um mtodo para informar se a fase est ativa.
Function Fase1_carregar() ;----------paredes----------;DE CIMA Parede_New("acima", 0, 0) Parede_New("acima", 50, 0) Parede_New("acima", 100, 0)

Ai est o inicio da funo de carregamento. Em sua primeira parte estamos construindo as paredes da fase. Para isso invocamos repetidamente o mtodo Parede_New e passamos a ele a identidade do bloco da parede e sua posio x e y na tela.
;---------------blocos----------Bloco_New(3, 110, 100) Bloco_New(3, 175, 100)

Em sua segunda parte, a funo de construo vai criar os blocos. Para isso passa 3 parmetros: a vida do bloco e suas posies x e y.
game\fase = 1 game\vidas = 2 game\scores = 0 game\combo = 0 Bola_reiniciar() MoveMouse(350,500)

No final da funo vamos reiniciar todo o sistema do jogo, afinal estamos na fase 1, que o inicio do jogo e isso importante, pois poderamos estar jogando uma segunda partida. Vamos agora para nossa segunda funo, a de descarregamento da fase.
Function Fase1_descarregar() Bloco_Delete() PAREDE_Delete() End Function

Veja que ela consiste simplesmente da invocao da funo de descarregamento dos blocos e das parede.
Function Fase1_Ativa() If Bloco_Existe() Return 1 End Function

Bloco_New(1, 370, 125) Bloco_New(1, 435, 125) Bloco_New(1, 500, 125) Bloco_New(1, 565, 125) Bloco_New(3, 630, 125) Bloco_New(3, 110, 150) Bloco_New(2, 175, 150) Bloco_New(2, 240, 150) Bloco_New(2, 305, 150) Bloco_New(2, 370, 150) Bloco_New(2, 435, 150) Bloco_New(2, 500, 150) Bloco_New(2, 565, 150) Bloco_New(3, 630, 150) Bloco_New(3, 110, 175) Bloco_New(1, 175, 175) Bloco_New(1, 240, 175) Bloco_New(1, 305, 175) Bloco_New(1, 370, 175) Bloco_New(1, 435, 175) Bloco_New(1, 500, 175) Bloco_New(1, 565, 175) Bloco_New(3, 630, 175) Bloco_New(3, 110, 200) Bloco_New(3, 175, 200) Bloco_New(3, 240, 200) Bloco_New(3, 305, 200) Bloco_New(3, 370, 200) Bloco_New(3, 435, 200) Bloco_New(3, 500, 200) Bloco_New(3, 565, 200) Bloco_New(3, 630, 200) game\fase = 1 game\vidas = 2 game\scores = 0 game\combo = 0 Bola_reiniciar() MoveMouse(350,500) End Function Function Fase1_descarregar() Bloco_Delete() PAREDE_Delete() End Function Function Fase1_Ativa() If Bloco_Existe() Return 1 End Function

colocamos o mouse na posio inicial, mudamos a varivel de controle de fase do jogo para a fase apropriada e reiniciamos os dados da bola: sua posio e velocidade.
Function Fase2_Descarregar() Bloco_Delete() PAREDE_Delete() End Function

Acima nossa funo para descarregar a fase.


Function Fase2_Ativa() If Bloco_Existe() Return 1 End Function

Essa funo verifica se existe algum bloco ativo na fase. CODIGO COMPLETO DE FASE2.BB
Function Fase2_carregar() ;----------paredes----------;DE CIMA Parede_New("acima", 0, 0) Parede_New("acima", 50, 0) Parede_New("acima", 100, 0) Parede_New("acima", 150, 0) Parede_New("acima", 200, 0) Parede_New("acima", 250, 0) Parede_New("acima", 300, 0) Parede_New("acima", 350, 0) Parede_New("acima", 400, 0) Parede_New("acima", 450, 0) Parede_New("acima", 500, 0) Parede_New("acima", 550, 0) Parede_New("acima", 600, 0) Parede_New("acima", 650, 0) Parede_New("acima", 700, 0) Parede_New("acima", 750, 0) ;ESQUERDA Parede_New("esquerda", 0, 0) Parede_New("esquerda", 0, 43) Parede_New("esquerda", 0, 86) Parede_New("esquerda", 0, 129) Parede_New("esquerda", 0, 172) Parede_New("esquerda", 0, 215) Parede_New("esquerda", 0, 258) Parede_New("esquerda", 0, 301) Parede_New("esquerda", 0, 344) Parede_New("esquerda", 0, 387) Parede_New("esquerda", 0, 430) Parede_New("esquerda", 0, 473) Parede_New("esquerda", 0, 516) ;ESQUERDA Parede_New("direita", 750, 0) Parede_New("direita", 750, 43) Parede_New("direita", 750, 86) Parede_New("direita", 750, 129) Parede_New("direita", 750, 172) Parede_New("direita", 750, 215) Parede_New("direita", 750, 258) Parede_New("direita", 750, 301) Parede_New("direita", 750, 344) Parede_New("direita", 750, 387) Parede_New("direita", 750, 430) Parede_New("direita", 750, 473) Parede_New("direita", 750, 516) ;---------------blocos----------Bloco_New(3, 110, 100) Bloco_New(3, 175, 100) Bloco_New(3, 240, 100)

Arquivo Fase2.bb Vamos agora ao arquivo de cdigo responsvel pelo gerenciamento da segunda fase do jogo, que bastante semelhante ao anterior.
Function Fase2_carregar() ;----------paredes----------;DE CIMA Parede_New("acima", 0, 0) Parede_New("acima", 50, 0)

Primeiro carregamos as paredes


;---------------blocos----------Bloco_New(3, 110, 100) Bloco_New(3, 175, 100)

Depois carregamos os blocos do jogo.


MoveMouse(350,500) game\fase = 2 Bola_reiniciar()

Devemos reiniciar alguns estados relativos a posio do batedor e da bola. Para isso

Bloco_New(3, 305, 100) Bloco_New(3, 370, 100) Bloco_New(3, 435, 100) Bloco_New(3, 500, 100) Bloco_New(3, 565, 100) Bloco_New(3, 630, 100) Bloco_New(2, 110, 125) Bloco_New(2, 175, 125) Bloco_New(1, 240, 125) Bloco_New(1, 305, 125) Bloco_New(1, 370, 125) Bloco_New(1, 435, 125) Bloco_New(1, 500, 125) Bloco_New(2, 565, 125) Bloco_New(2, 630, 125) Bloco_New(2, 110, 150) Bloco_New(2, 175, 150) Bloco_New(1, 240, 150) Bloco_New(1, 305, 150) Bloco_New(1, 370, 150) Bloco_New(1, 435, 150) Bloco_New(1, 500, 150) Bloco_New(2, 565, 150) Bloco_New(2, 630, 150) Bloco_New(2, 110, 175) Bloco_New(2, 175, 175) Bloco_New(1, 240, 175) Bloco_New(1, 305, 175) Bloco_New(1, 370, 175) Bloco_New(1, 435, 175) Bloco_New(1, 500, 175) Bloco_New(2, 565, 175) Bloco_New(2, 630, 175) Bloco_New(3, 110, 200) Bloco_New(3, 175, 200) Bloco_New(3, 240, 200) Bloco_New(3, 305, 200) Bloco_New(3, 370, 200) Bloco_New(3, 435, 200) Bloco_New(3, 500, 200) Bloco_New(3, 565, 200) Bloco_New(3, 630, 200) MoveMouse(350,500) game\fase = 2 Bola_reiniciar() End Function Function Fase2_Descarregar() Bloco_Delete() PAREDE_Delete() End Function Function Fase2_Ativa() If Bloco_Existe() Return 1 End Function

Include Include Include Include Include Include Include Include

"menu.bb" "bloco.bb" "batedor.bb" "bola.bb" "parede.bb" "fase1.bb" "fase2.bb" "Creditos.bb"

Para que os cdigos que esto nos arquivos auxiliares do projeto possam ter validade no nosso jogo eles tm que ser includos no nosso cdigo principal por meio do comando Include.
;declarando a estrutura do jogo Type Tgame Field fundo Field som_batedor Field som_bloco Field som_morre Field scores Field vidas Field fase Field combo Field state End Type

Aqui estamos declarando a estrutura de dados do nosso jogo. Esses dados iro controlar o aspecto geral do jogo, como pontuao, fase atual, vidas, sons.
;configurando estados iniciais Global game.Tgame = New Tgame game\fundo = LoadSound ("midia\background.jpg") game\som_batedor = LoadSound ("midia\som2.wav") game\som_bloco = LoadSound ("midia\som1.wav") game\som_morre = LoadSound ("midia\som3.wav") game\scores = 0 game\vidas = 2 game\fase = 0 game\combo = 0 game\state = 0

Aqui estamos definindo o estado inicial do jogo, dando os parmetros iniciais para as variveis de controle.
Creditos_Abrir()

Arquivo Game.bb Esse o nosso arquivo principal; ele o responsvel pela combinao e ordenao de todos os elementos de forma lgica resultando em um jogo. Vamos estud-lo passo a passo.
Graphics 800, 600 SetBuffer BackBuffer()

Fazemos a invocao da tela de apresentao do jogo


menu_exibir()

E transferimos o controle do programa para o loop do menu.


;XXXXXXXXXXXXXXXXXX GAME LOOP XXXXXXXXXXXXXXXXX While (1) Controle() Logica() Fisica() Colisao() Desenha() Flip Cls Wend

Aqui estamos configurando o modo grfico do jogo. A resoluo ser de 800x600 e iremos usar o sistema de dois buffers para imagem.

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX

Esse o loop de controle do jogo, ele possui toda a lgica de processamento e controle do jogo. Ele s executado quando o jogador no menu pressiona a tecla iniciar. Veja que o loop faz a invocao de 5 funes do prprio arquivo Game.bb. Essas funes possuem toda a lgica do jogo e controlam todos os demais elementos envolvidos. Abaixo temos o cdigo de todas as funes.
;--------------------LOGICA-------------------Function Logica()

menu_exibir() EndIf EndIf

Todo esse bloco de cdigo executa se perdermos uma bola If Bola_Morreu(), isso , se a bola passar da linha inferior da tela. Veja que esse teste feito por uma funo do arquivo Bola.bb. J que perdemos uma bola, vamos acionar um efeito sonoro para enfatizar que isso aconteceu.
PlaySound game\som_morre

Aqui iniciamos a nossa funo de lgica do jogo


;Fase1 END If game\fase = 1 If Fase1_Ativa() Else Fase1_Descarregar() Fase2_Carregar() game\state = 0 EndIf EndIf

O passo seguinte tirar uma vida da nossa varivel de vidas, colocarmos o jogo em estado de espera e reiniciar os dados de controle da bola.
game\vidas = game\vidas - 1 game\state = 0 Bola_reiniciar()

O ltimo passo dessa funo mais complicado veja abaixo:


If game\vidas < 0 If game\fase = 1 Then Fase1_Descarregar() If game\fase = 2 Then Fase2_Descarregar() menu_exibir() EndIf

A primeira parte dessa funo verifica se a fase em jogo a fase 1 If game\fase = 2 e se isso for verdadeiro, se ela est ativa If Fase2_Ativa(). Caso no esteja, invoca a funo para descarregar a fase da memria Fase1_Descarregar(), carrega a fase 2 Fase2_Carregar() e coloca a bola em estado de espera game\state = 0.
;Fase2 END If game\fase = 2 If Fase2_Ativa() Else Fase2_Descarregar() menu_exibir() EndIf EndIf

J que tiramos uma vida, tambm devemos verificar se ainda existem vidas. Se a nossa varivel menor que zero sinal que no nos resta vida e, portanto, estamos mortos. Esse o momento de chamarmos funes para descarregar o jogo, veja que descarregamos a fase ativa.
;--------------------FISICA-------------------Function Fisica() If game\state = 1 Bola_fisica() Else bola\px = batedor\px + 40 bola\py = 500 End If End Function

A segunda parte da funo verifica se a fase atual a fase 2 If game\fase = 2 e se possui ou no blocos com vida If Fase2_Ativa(). Caso isso seja falso, descarrega os dados da fase Fase2_Descarregar() e entra no menu menu_exibir() pois acabaram as fases do jogo.
;bola morta If Bola_Morreu() PlaySound game\som_morre game\vidas = game\vidas - 1 game\state = 0 Bola_reiniciar() If game\vidas < 0 ; CHAMAR SCORES If game\fase = 1 Then Fase1_Descarregar() If game\fase = 2 Then Fase2_Descarregar()

Nossa funo de controle de fsica bem simples, afinal o grosso da fsica est no arquivo Bola.bb.
If game\state = 1 Bola_fisica()

O que fizemos acima condicionar a ativao da fsica ao estado do jogo. Se o estado for de espera, (0) a fsica no executa.
Else bola\px = batedor\px + 40 bola\py = 500 End If

Se estivermos no estado de espera (0) ento esse trecho acima executado. Esse cdigo

garante que a bola fique esttica, seguindo o batedor.


;--------------------COLISAO-------------------Function Colisao() Bola_colide() End Function

Nossa funo principal de coliso s tem o trabalho de gerenciar as colises da bolinha, pois nesse jogo s ele se movimenta. Por isso a nica que coisa que ela faz invocar esse controle.
;--------------------DESENHA-------------------Function Desenha() DrawImage game\fundo, 0, 0 Bola_draw() Batedor_draw() Bloco_draw() Parede_draw() Text 50,10, "PONTOS: " + game\scores Text 685,10,"VIDAS: " + game\vidas End Function

Acima a nossa ultima funo de controle, responsvel por gerencia a exibio de todas as imagens. Veja que ela invoca uma por uma as funes de exibio de cada objeto que possui uma imagem. Por fim, essa funo exibe os dados de vida e pontos na tela por meio do comando text. CODIGO COMPLETO DE GAME.BB
Graphics 800, 600 SetBuffer BackBuffer() Include "menu.bb" Include "bloco.bb" Include "batedor.bb" Include "bola.bb" Include "parede.bb" Include "fase1.bb" Include "fase2.bb" Include "Creditos.bb" ;declarando a estrutura do jogo Type Tgame Field fundo Field som_batedor Field som_bloco Field som_morre Field scores Field vidas Field fase Field combo Field state End Type ;configurando estados iniciais Global game.Tgame = New Tgame game\fundo = LoadSound ("midia\background.jpg") game\som_batedor = LoadSound ("midia\som2.wav") game\som_bloco = LoadSound ("midia\som1.wav") game\som_morre = LoadSound ("midia\som3.wav") game\scores = 0

game\vidas = 2 game\fase = 0 game\combo = 0 game\state = 0 Creditos_Abrir() menu_exibir() ;XXXXXXXXXXXXXXXXXX GAME LOOP XXXXXXXXXXXXXXXXX While (1) Controle() Logica() Fisica() Colisao() Desenha() Flip Cls Wend ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXX ;-------------------CONTROLE------------------Function Controle() mx = MouseX() my = MouseY() Batedor_Mover(mx, my) click = MouseHit(1) If game\state = 0 If click Then game\state = 1 EndIf If KeyHit(1) Then menu_exibir() End Function ;--------------------LOGICA-------------------Function Logica() ;Fase1 END If game\fase = 1 If Fase1_Ativa() Else Fase1_Descarregar() Fase2_Carregar() game\state = 0 EndIf EndIf ;Fase2 END If game\fase = 2 If Fase2_Ativa() Else Fase2_Descarregar() menu_exibir() EndIf EndIf ;bola morta If Bola_Morreu() PlaySound game\som_morre game\vidas = game\vidas - 1 game\state = 0 Bola_reiniciar() If game\vidas < 0 If game\fase = 1 Then Fase1_Descarregar() If game\fase = 2 Then Fase2_Descarregar() menu_exibir() EndIf EndIf End Function

;--------------------FISICA-------------------Function Fisica() If game\state = 1 Bola_fisica() Else bola\px = batedor\px + 40 bola\py = 500 End If End Function ;--------------------COLISAO-------------------Function Colisao() Bola_colide() End Function ;--------------------DESENHA-------------------Function Desenha() DrawImage game\fundo, 0, 0 Bola_draw() Batedor_draw() Bloco_draw() Parede_draw() Text 50,10, "PONTOS: " + game\scores Text 685,10,"VIDAS: " + game\vidas End Function

Ultimo passo: testes O ultimo passo de um processo de desenvolvimento de jogos testar, isso jogar em busca de encontrar eventuais erros. Duvido muito que algum discorde que essa a melhor fase, mas ela pode ser bastante cansativa em alguns jogos, afinal temos que testar todas as possibilidades e combinaes de possibilidades. Minhas fontes Como voc pode perceber, em um jogo temos textos estticos como, por exemplo, o ttulo do jogo, os crditos, a palavra vidas ou scores ou textos dinmicos, como por exemplo nome das pessoas que integram um rank de scores ou mensagens enviadas em um jogo multiplay. Usar o comando Text para isso fica muito deselegante pois esse comando s existe para usarmos em tempo de desenvolvimento, como ferramenta de exibio de dados atuais para debugar o jogo. Os textos estticos, como nunca mudam, ns podemos os fazer com uma s imagem, mas os textos dinmicos no podem ser feitos assim, pois seria impossvel prever quais imagens criar. Para isso devemos criar nossas prprias fontes de bitmaps e uma funo que permita converter textos para essas imagens. isso que vamos aprender agora. O primeiro passo criar um arquivo de imagem animada com os caracteres que desejamos exibir.

<![endif]> Criar imagens de letras pequenas com boa qualidade algo muito difcil de ser conseguido. Uma estratgia muito boa para obter um resultado melhor usar o fundo para o texto com a mesma cor do fundo onde o texto vai ser exibido. Assim podemos deixar a suavizao acionada no momento de exportar a imagem e conseguiremos um timo resultado na aplicao final. A imagem acima foi concebida nessa filosofia ela possui apenas 20x20 em cada letra. Veja que com o fundo branco ela fica com uma aparncia ruim, mas ao exibi-la em um fundo preto no Blitz3D ela vai ter outra aparncia, pois ela foi criada com suavizao com um fundo preto e ento s deve ser usada com esse tipo de fundo. Para imagens de letras maiores, a partir de 50 pontos, j d para ter uma boa qualidade sem suavizao, portanto para fontes grandes seria melhor usar essa outra tcnica, para possibilitar maior flexibilidade de uso. Vamos parte prtica... Exemplo 1
Graphics 800, 600 Global fonte = LoadAnimImage("midia\fonte.png", 20, 20, 0, 36) MaskImage fonte, 255, 255, 255 wrmtexto ("Pontos 999123567", 100, 100) wrmtexto ("Wrmsoft is the best", 100, 150) WaitKey Function wrmtexto( msg$, px, py) msg$ = Lower$(msg$) tamanho = Len(msg$) For x = 1 To tamanho letra$ = Mid$(msg$, x, 1) pxf = px + ((x * 15) - 15) If letra$ = "a" Then DrawImage fonte, pxf, py, 0 If letra$ = "b" Then DrawImage fonte, pxf, py, 1 If letra$ = "c" Then DrawImage fonte, pxf, py, 2 If letra$ = "d" Then DrawImage fonte, pxf, py, 3 If letra$ = "e" Then DrawImage fonte, pxf, py, 4 If letra$ = "f" Then DrawImage fonte, pxf, py, 5 If letra$ = "g" Then DrawImage fonte, pxf, py, 6

If letra$ = "h" pxf, py, 7 If letra$ = "i" pxf, py, 8 If letra$ = "j" pxf, py, 9 If letra$ = "k" pxf, py, 10 If letra$ = "l" pxf, py, 11 If letra$ = "m" pxf, py, 12 If letra$ = "n" pxf, py, 13 If letra$ = "o" pxf, py, 14 If letra$ = "p" pxf, py, 15 If letra$ = "q" pxf, py, 16 If letra$ = "r" pxf, py, 17 If letra$ = "s" pxf, py, 18 If letra$ = "t" pxf, py, 19 If letra$ = "u" pxf, py, 20 If letra$ = "v" pxf, py, 21 If letra$ = "w" pxf, py, 22 If letra$ = "x" pxf, py, 23 If letra$ = "y" pxf, py, 24 If letra$ = "z" pxf, py, 25 If letra$ = "0" pxf, py, 26 If letra$ = "1" pxf, py, 27 If letra$ = "2" pxf, py, 28 If letra$ = "3" pxf, py, 29 If letra$ = "4" pxf, py, 30 If letra$ = "5" pxf, py, 31 If letra$ = "6" pxf, py, 32 If letra$ = "7" pxf, py, 33 If letra$ = "8" pxf, py, 34 If letra$ = "9" pxf, py, 35 Next End Function

Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte,

Global fonte = LoadAnimImage("midia\fonte.png", 20, 20, 0, 36) MaskImage fonte, 255, 255, 255

Nas linhas abaixo estamos usado a funo para exibir os textos


wrmtexto ("Pontos 999123567", 100, 100) wrmtexto ("Wrmsoft is the best", 100, 150)

Vejamos o cabealho de nossa funo


Function wrmtexto( msg$, px, py)

Veja que ela aceita uma string e a posio na qual ela dever ser exibida.
msg$ = Lower$(msg$)

O passo seguinte foi deixar todas os caracteres como minsculos por meio do comando Lower.
tamanho = Len(msg$)

Aqui estamos descobrindo o tamanho da string, isso , quantos caracteres ela tm.
For x = 1 To tamanho

Usamos essa informao do tamanho da string para criar um loop que passe por todas as letras uma por uma. Da o loop comea de 1 e vai at o tamanho da string.
letra$ = Mid$(msg$, x, 1)

Aqui estamos usando o comando Mid$ para extrair as letras da string, uma de cada vez. A posio da letra a ser removida dada de acordo com o valor atual de x.
pxf = px + ((x * 15) - 15)

O que fazemos aqui definirmos dinamicamente onde as letras devero aparecer. Como elas tem uma rea til de mais ou menos 15 pontos, estou multiplicando esse valor pela varivel x e somando a posio inicial.
If letra$ = "a" Then DrawImage fonte, pxf, py, 0

A primeira coisa a fazer foi acionar o modo grfico


Graphics 800, 600

O passo seguinte exibir a imagem de acordo com a letra atual no ciclo do loop. Isso foi feito manualmente para cada caractere existente no arquivo, mas poderamos ter feito essa etapa dinamicamente tambm, se usssemos os nmeros ASC de cada caractere. Preferimos assim por mais fcil de visualizar o que est acontecendo. Como voc pode perceber, as imagens so exibidas com altssima perfeio em um fundo preto. Mas faa um teste. Execute o prximo exemplo, onde exibimos um retngulo branco no fundo das letras. Exemplo 2
Graphics 800, 600 Global fonte = LoadAnimImage("midia\fonte.png", 20, 20, 0, 36) MaskImage fonte, 255, 255, 255

Vamos agora carregar a imagem e aplicar uma mscara de cor.

Rect 50, 50, 500, 200,1 wrmtexto ("Numeros 0123456789", 100, 100) wrmtexto ("Letras abcdefghijklmnopqrstuvwxyz", 100, 150) WaitKey Function wrmtexto( msg$, px, py) msg$ = Lower$(msg$) tamanho = Len(msg$) For x = 1 To tamanho letra$ = Mid$(msg$, x, 1) pxf = px + ((x * 15) - 15) If letra$ = "a" Then DrawImage fonte, pxf, py, 0 If letra$ = "b" Then DrawImage fonte, pxf, py, 1 If letra$ = "c" Then DrawImage fonte, pxf, py, 2 If letra$ = "d" Then DrawImage fonte, pxf, py, 3 If letra$ = "e" Then DrawImage fonte, pxf, py, 4 If letra$ = "f" Then DrawImage fonte, pxf, py, 5 If letra$ = "g" Then DrawImage fonte, pxf, py, 6 If letra$ = "h" Then DrawImage fonte, pxf, py, 7 If letra$ = "i" Then DrawImage fonte, pxf, py, 8 If letra$ = "j" Then DrawImage fonte, pxf, py, 9 If letra$ = "k" Then DrawImage fonte, pxf, py, 10 If letra$ = "l" Then DrawImage fonte, pxf, py, 11 If letra$ = "m" Then DrawImage fonte, pxf, py, 12 If letra$ = "n" Then DrawImage fonte, pxf, py, 13 If letra$ = "o" Then DrawImage fonte, pxf, py, 14 If letra$ = "p" Then DrawImage fonte, pxf, py, 15 If letra$ = "q" Then DrawImage fonte, pxf, py, 16 If letra$ = "r" Then DrawImage fonte, pxf, py, 17 If letra$ = "s" Then DrawImage fonte, pxf, py, 18 If letra$ = "t" Then DrawImage fonte, pxf, py, 19 If letra$ = "u" Then DrawImage fonte, pxf, py, 20 If letra$ = "v" Then DrawImage fonte, pxf, py, 21 If letra$ = "w" Then DrawImage fonte, pxf, py, 22 If letra$ = "x" Then DrawImage fonte, pxf, py, 23 If letra$ = "y" Then DrawImage fonte, pxf, py, 24 If letra$ = "z" Then DrawImage fonte, pxf, py, 25 If letra$ = "0" Then DrawImage fonte, pxf, py, 26

If letra$ = "1" pxf, py, 27 If letra$ = "2" pxf, py, 28 If letra$ = "3" pxf, py, 29 If letra$ = "4" pxf, py, 30 If letra$ = "5" pxf, py, 31 If letra$ = "6" pxf, py, 32 If letra$ = "7" pxf, py, 33 If letra$ = "8" pxf, py, 34 If letra$ = "9" pxf, py, 35 Next End Function

Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte, Then DrawImage fonte,

Exerccios 1. Crie um arquivo animado com fontes para seus projetos. Coloque nele outros caracters que tambm so muito usados, como pontuao, maisculas, etc. 2. Volte ao projeto do jogo DeskTroy e substitua os textos por textos em imagens. 3. Crie a funcionalidade de melhores escores para o jogo DeskTroy. Esses dados devero ser salvos em arquivo de dados para que os placares no sejam perdidos. 4. Crie mais fases para o jogo.

Você também pode gostar