Você está na página 1de 46

3.

PROGRAMAO: PARTE I Nessa seo vamos fazer um estudo dos comandos de controle do Blitz3D, aqueles que permitem que os programas tomem decises e assim consigam raciocinar, isso , criar inteligncia artificial. Para fazer isso, usamos comandos condicionais, operadores relacionais, operadores lgicos, operadores matemticos e comandos de repeties. Vamos abordar um de cada vez. Tambm vamos abordar a principal estrutura de organizao de cdigo: as funes. Nosso objetivo nesse tpico, e no tpico posterior, dar fundamentos de programao para que, a partir do modulo 5 iniciemos a pratica de desenvolvimento de jogos. Operadores matemticos Os operadores matemticos so utilizados para efetuar clculos matemticos no ambiente de programao. O objetivo aqui no estudar todos os operadores e funes matemticas que existem, mas apenas aqueles que so mais utilizados em jogos. Em um jogo, a matemtica usada, por exemplo, para calcular quantos tiros um jogador ainda tem para disparar, para traar rotas de tiros em parbolas ou at mesmo para gerenciar a fsica de jogos de carros ou avies. Voc vai ter que se acostumar a ela para criar bons jogos. Soma Podemos efetuar somas com o Blitz3D por meio do operador de soma que representado pelo sinal de mais +. O resultado da soma deve ser guardado em uma varivel, seno se perder. Exemplo 1
soma = 1 + 1 Print soma WaitKey

resistncia do escudo mais a resistncia da armadura. Exemplo 2


armadura = 3 escudo = 4 Heroi_resistencia = armadura + escudo Print "Heroi Resistencia: " + Heroi_resistencia WaitKey

Subtrao A subtrao realizada por meio do smbolo -. Da mesma forma que ocorre com a operao de soma, necessrio armazenar o resultado dentro de uma varivel para no perder o mesmo. No exemplo abaixo um inimigo desfere um golpe contra nosso Heri. O golpe primeiro ser amenizado pela resistncia do Heri e s depois ir gerar o dano, pois o dano real recebido igual a fora do golpe, menos a fora do sistema de defesa. Exemplo 3
golpe = 10 Heroi_resistencia = 5 Heroi_vida = 100 golpe = golpe - Heroi_resistencia Print "Golpe amenizado pela resistencia: " + golpe Heroi_vida = Heroi_vida - golpe Print "Vida Depois do Golpe: " + Heroi_vida WaitKey

Multiplicao A multiplicao implementada por meio do caractere estrela *. Exemplo 4


mult = 2 * 2 Print mult WaitKey

O exemplo acima mostra um caso simples de soma. Somamos duas unidades e colocamos o resultado dentro da varivel soma. A seguir, damos um exemplo de soma de duas variveis onde a resistncia total do heroi dada pela
1

Um exemplo um pouco mais complexo de multiplicao. Como prmio por fazer um favor a um feiticeiro, ele nos deu uma espada mgica que aumenta nossa fora em 20%. Para indicar essa influncia sobre o nosso heri, vamos multiplicar a fora real dele por 1.2, assim teremos os 20%. Exemplo 5
Espada_forca# = 1.2

Heroi_forca# = 50 Print "Forca atual do heroi: " + Heroi_forca# Heroi_forca# = Heroi_forca# * Espada_forca# Print "Forca do heroi com espada: " + Heroi_forca# WaitKey

Diviso O clculo de diviso realizado no Blitz3D por meio do operador barra /. Exemplo 6
div = 21 / 3 Print "Resultado da diviso: " + div WaitKey

algumas moedas. Pelo calculo que fizemos acima isso se perderia, pois o Blitz3D ia arredondar o clculo. Venha no exemplo abaixo que temos uma quantidade de dinheiro que no pode ser dividida com perfeio por 3, mas agora usamos o operador Mod para pegar o resto da operao. Assim, o nosso heri poder ficar com o que sobrar da diviso, afinal, no d para dividir moedas de ouro ao meio. Exemplo 8
Heroi_conta = 1202 Qtd_pessoas = 3 resultado = Heroi_conta / Qtd_pessoas Print "Resultado da diviso: " + resultado resto = Heroi_conta Mod Qtd_pessoas Print "O resto da diviso: " + resto Heroi_conta = resultado + resto Print "A conta do heroi tem: " + Heroi_conta WaitKey

Nosso heri e seus dois companheiro chegaram em uma encruzilhada. Existem trs caminhos a seguir e cada um deve ir por um lado diferente. Para que nenhum deles mora de fome ou por necessidades pelo caminho, nosso heroi vai ter que repartir o alimento e o dinheiro com os dois colegas. Exemplo 7
Qtd_pessoas = 3 Heroi_conta = 1200 Heroi_alimento = 300 Heroi_conta = Heroi_conta / Qtd_pessoas Heroi_alimento = Heroi_alimento / Qtd_pessoas Print "Alimento atual: " + Heroi_alimento Print "Dinheiro atual: " + Heroi_conta Waitkey

Perceba que, para obtermos o resto de uma operao de diviso, basta montarmos a mesma operao e substituir a barra de diviso / por Mod. Raiz quadrada A raiz quadrada de um nmero um numero que, se multiplicado por ele mesmo gera o primeiro. Assim, a raiz quadrada de 4 2, pois 2 x 2 = 4. A raiz de 9 3, pois 3 x 3 = 9. Para descobrirmos a raiz quadrada de um nmero usamos a funo [Sqr( )]. A operao de raiz quadrada muito importante para fsica de jogos, clculos de fora e colises matemticas. Exemplo 9
Print "A raiz de 9 : " + Sqr(9) Print "A raiz de 3 : " + Sqr(3) WaitKey

Resto O Operador Mod responsvel por retornar o resto de uma operao de diviso. Quando dividimos um nmero por outro, s vezes a diviso inteira e no sobra resto, por exemplo (4/2=2) onde o resto 0. Mas, se dividirmos (5/2=2) o resto 1. Esse 1 de resto perdido se o sistema no o capturar de alguma forma. A forma de capturar o resto de uma diviso usar o operador Mod. O clculo de resto muito importante para o gerenciamento de mapas complexos e criao de sistemas infinitos, mas isso ser estudado mais frente. O importante aqui voc aprender a como fazer essa operao. No exemplo anterior, de diviso de alimento e dinheiro, imagine que tivssemos um valor que no daria uma diviso perfeita, isso , sobrasse
2

Para demonstrar algumas das funcionalidades da raiz quadrada, abaixo criamos um exemplo do uso dela para calcular a distncia entre dois pontos. Uma funcionalidade como essa muito importante para inteligncia artificial de unidades inimigas controladas pelo computador. Elas normalmente atacam a partir do momento que o

personagem chegue a uma certa distncia de um soldado inimigo, sua rea de viso. Exemplo 10
Graphics 400,300 SeedRnd MilliSecs() AX = Rnd(50, 350) AY = Rnd(50, 250) BX = Rnd(50, 350) BY = Rnd(50, 250) Color 255,0,0 Plot AX, AY Plot BX, BY xd = BX - AX yd = BY - AY DISTANCIA = Sqr((xd^2) + (yd^2)) Print "A DISTANCIA ENTRE OS DOIS : " + DISTANCIA WaitKey

distncia dos dois pontos igual raiz quadrada (Sqr) da soma do quadrado das distncias x e y.
xd = BX - AX yd = BY - AY DISTANCIA = Sqr((xd^2) + (yd^2))

O condicional If O operador de condio If com certeza o mais importante comando de controle que existe em qualquer linguagem de programao. Esse operador testa uma condio e se essa condio for verdadeira, ele executa um comando ou um bloco de comandos. Veja alguns exemplos lgicos cotidianos de usos de comando condicional If. Lembre-se, If significa "Se" e Then significa "Ento" Em jogos: Lgica: Se apertar a tecla barra de espao, dispare um tiro. Cdigo: If KeyHit(57) Then Disparar() Lgica: Se a vida for igual a 0 ento o jogador deve morrer. Cdigo: If vida=0 Then Morrer() Lgica: Se nosso heri levar um tiro, isso , se ele colidir com um tiro, perde 10 de vida. Cdigo: If Colide(heroi, tiro) Then vida = vida - 10 Em programas em geral: Lgica: Um terminal dispenser de um banco s libera o dinheiro se o saldo for maior que o valor solicitado para o saque. Cdigo: If Saldo > Saque Then Sacar(Saque) Lgica: Uma venda em uma loja virtual s ser possvel se existirem produtos no estoque, isso , se o estoque maior que zero. Cdigo: If Produto_estoque > 0 Then Produto_vender() Como voc pode ver, realmente o condicional If a base de praticamente todo tipo de deciso que um programa de computador toma. por meio dele que fazemos a mquina "pensar". Assim, podemos dizer que ele tambm o principal comando de interao entre o homem e a mquina e jogos so essencialmente interao. Como o If funciona?
3

Nessa aplicao usamos o comando Rnd() para gerar posies aleatrias, ele semeado pelo comando SeedRnd MilliSecs() que dessa forma garante que os valores sorteados sero sempre diferentes.Os numeros que esto dentro de Rnd limitam o escopo do sorteio, assim Rnd(50,250) se limita a sortear um numero entre 50 e 250.
SeedRnd MilliSecs() AX = Rnd(50, 350) AY = Rnd(50, 250) BX = Rnd(50, 350) BY = Rnd(50, 250)

Tambm usamos o comando Color para mudar a cor da paleta de desenho; esse comando recebe saturaes red, green e blue, assim, o comando Color 255,0,0 deixa a paleta de desenho na cor vermelha (red=255).
Color 255,0,0

Para exibir os pontos usamos o comando Plot que exibe um ponto de 1 pixel na tela. Esse comando precisa de apenas dois parmetros para funcionar, a posio x e a posio y em que dever ser exibido.
Plot AX, AY Plot BX, BY

O operador "^" de exponenciao, isso diz quantas vezes um nmero multiplicado por ele mesmo. Dessa forma "x^2" o mesmo que "x*x" e "x^3" o mesmo que "x*x*x". Assim, a

O condicional If s compreende dois tipos de dados Verdadeiro (true) ou Falso (false). Para ele, o nmero 0 (zero) significa falso, e todo nmero diferente de zero verdadeiro, assim 1 verdadeiro, -50 verdadeiro e assim por diante. Veja no exemplo abaixo que colocamos o zero como condio de teste para o if, e por isso o comando no executa, pois zero falso. Exemplo 11
If 0 Then Print "passou no teste" Print "Fim" WaitKey

If (a=1) Then Print "A passou no teste (a=1)" If (a=2) Then Print "A passou no teste (a=2)" WaitKey

Para manter a compatibilidade com a sintaxe da linguagem Basic, Mark Sibly manteve o comando auxiliar Then para o If. Ele muito til para iniciantes, pois ele separa visualmente a condio do comando a ser executado criando a sequncia lgica do tipo: If condio Then comando Mas ele no obrigatrio e seus algoritmos vo funcionar normalmente sem o uso dele. Veja o exemplo anterior feito sem o uso dos mesmos. Exemplo 14
a=1 If (a=1) Print "A passou no teste (a=1)" If (a=2) Print "A passou no teste (a=2)" WaitKey

Agora vamos substituir o zero por outro numero qualquer e o comando vai executar, pois qualquer nmero diferente de zero verdadeiro. Exemplo 12
If 999 Then Print "passou no teste" Print "Fim" WaitKey

O que devemos entender que o Blitz3D troca a condio por verdadeiro ou falso. Quando ele encontra o nmero zero, troca esse por falso e se encontra outro nmero, troca o mesmo por verdadeiro. Assim se d tambm com as demais condies, como verificaes de comparao ou funes. A maioria das funes sempre retornam um valor e por meio desse valor que o blitz3d faz a verificao de falso e verdadeiro. No caso de comparaes mais simples, pois comparaes sempre retornam verdadeiro ou falso. veja algumas comparaes:
If (1 = 1) -> verdadeiro If (2 = 1) -> falso x=5 If (x=5) -> verdadeiro If (x=x) -> verdadeiro If (x=3) -> falso If (x=y) -> falso (como y no foi declarado, ele igual a zero).

Os parnteses tambm no so obrigatrios na seo de teste de condio, mas aconselho usar os mesmos para no misturar visualmente uma coisa com outra. Quanto mais legvel um programa, menos demorada e menos cansativa ser sua compreenso e manuteno. Primeira aplicao com deciso Aprendemos a fazer o computador tomar decises e interagir com o usurio por meio do comando If. Nessa aplicao simples, o usurio poder escolher o que o computador ir fazer por ele, e o computador vai obedecer. Exemplo 15
Graphics 640, 480 Text 10, 10, "********************** PC OBEDIENTE *************************" Text 10, 50, "[1] Ordene ao computador para Puxar o saco do Mark Sibly" Text 10, 80, "[2] Pegunte a ele sobre a UniDev" Text 10, 110, "[3] Mande ele dizer qual o melhor programa para jogos" Locate 10, 150 opt = Input$(" DIGITE O NUMERO DA OPO E APERTE ENTER: ") Cls Text 10, 10, "********************** PC OBEDIENTE *************************" If (opt = 1) Text 10, 50, "O Mark o Melhor arquiteto e programador do mundo!" If (opt = 2) Text 10, 50, "A UniDev The Best, s aqui vc encontra tudo sobre jogos!"

No exemplo abaixo provamos a tese acima. Declaramos a varivel "a=1" e fazemos testes. Veja que s o primeiro teste concludo com sucesso e assim, s o primeiro comando Print executado. Exemplo 13
a=1

If (opt = 3) Text 10, 50, "Isso fcil, O BLITZ3D!" If (opt < 1 Or opt > 3) Text 10, 50, "Opo invlida!" WaitKey

Na primeira linha configuramos o tamanho da tela:


Graphics 640, 480

Nas linhas subseqentes apenas exibimos mensagens na tela:


Text 10, 10, "********************** PC OBEDIENTE *************************" Text 10, 50, "[1] Ordene ao computador para Puxar o saco do Mark Sibly" Text 10, 80, "[2] Pegunte a ele sobre a UniDev" Text 10, 110, "[3] Mande ele dizer qual o melhor programa para jogos" Com o comando Locate, posicionamos o curso na

posio "10, 150" para a partir dali executarmos a entrada de dados via teclado pelo comando Input.
Locate 10, 150 opt = Input$(" DIGITE O NUMERO DA OPO E APERTE ENTER: ") Usamos o comando Cls para limpar a tela das

Graphics 640, 480 Text 100, 100, "************************************************ ******" Text 100, 112, "********************* ADIVINHA ***********************" Text 100, 124, "************************************************ ******" Text 100, 160, "O Blitz3D sorteou um nmero de 1 a 5, adivinha qual ." Locate 130, 190 opt = Input$(" Sua tentativa : ") SeedRnd MilliSecs() numero = Rnd(1,5) Cls Color 0,255,0 If opt = numero Text 250, 150, "Voc O CARA!" If opt <> numero Text 280, 150, "ERROU!" WaitKey

exibies anteriores.
Cls

Veja que nesse exemplo usamos o gerador de nmeros aleatrios Rnd(1,5) para sortear um nmero de 1 a 5. Ele semeado pelo comando SeedRnd para que a cada vez que o programa for executado d nmeros diferentes.
SeedRnd MilliSecs() numero = Rnd(1,5)

Dai ento fazemos as novas exibies a partir da deciso tomada. Se escolhemos a opo 1, a segunda linha ser exibida; se escolhemos 2, a terceira linha ser exibida; caso nossa opo foi 3, a ltima linha monstrada. A primeira linha sempre ser exibida e caso tenhamos digitado um valor desconhecido, (se a opo menor que 1 ou a opo maior que 3) exibida uma mensagem de aviso.
Text 10, 10, "********************** PC OBEDIENTE *************************" If (opt = 1) Text 10, 50, "O Mark o Melhor arquiteto e programador do mundo!" If (opt = 2) Text 10, 50, "A UniDev The Best, s aqui vc encontra tudo sobre jogos!" If (opt = 3) Text 10, 50, "Isso fcil, O BLITZ3D!" If (opt < 1 Or opt > 3) Text 10, 50, "Opo invlida!"

O resultado exibido em cor verde, para isso usamos o comando Color para mudar a cor da paleta de desenho.
Color 0,255,0

Se o nmero escolhido o mesmo que o sorteado, voc vence, caso contrrio, perde. O operador "<>" significa diferente.
If opt = numero Text 250, 150, "Voc O CARA!" If opt <> numero Text 280, 150, "ERROU!"

Meu primeiro Jogo Agora que voc j teve uma breve introduo ao condicional if, j capaz de fazer o computador raciocinar e assim, j pode criar alguns tipos de jogos. Nosso primeiro jogo vai ser bem simples, ser um jogo de adivinhao. O Blitz3D vai sortear um nmero e voc ter que adivinhar qual . Exemplo 16
5

Operadores relacionais Os operadores relacionais tm a funo de efetuar comparaes entre dois valores ou variveis. Eles so muito importante para oferecer suporte aos comandos condicionais, pois so eles que fazem as principais comparaes para os condicionais poderem tomar decises. Os principais operadores relacionais so: de igualdade, maior, menor, maior ou igual, menor ou igual e diferente. Operador de igualdade O operador de igualdade no Blitz3D o mesmo que o operador de atribuio =. A funo desse

operador comparar dois valores ou variveis para verificar se seus valores so idnticos. Veja um caso onde o jogador possui uma chave e, para passar de fase, precisa passar por uma porta trancada. Verificamos se a chave da porta a mesma chave que o jogador possui e caso isso seja verdadeiro, a porta se abre. Exemplo 17
MinhaChave$ = "branca" ChaveDaPorta$ = "branca" If (MinhaChave$=ChaveDaPorta$) Print "Pode Entrar" WaitKey

Print "Acabaram os tiros" WaitKey

A primeira coisa que fizemos foi configura o tamanho da tela para 400 por 300.
Graphics 400, 300

Definimos a quantidade de tiros iniciais como 10.


tiros = 10

Aqui eximimos uma mensagem e logo aps mudamos a cor da paleta de desenho para vermelho, assim os tiros sero vermelhos.
Text 10, 10, "Aperte Space para disparar!" Color 255, 0, 0

Operador maior que O operador que implementa a relao maior que o operador >. Com esse operador podemos testar se um valor ou varivel maior que outro valor ou varivel. Exemplos comuns de uso do operador maior que, para controle de vidas, vitalidade e tiros. Para dar um tiro, sua munio deve ser "maior que zero". Se sua vitalidade no for maior que zero, voc morre. Se o seu nmero de vidas no for maior que zero, o jogo acaba. Exemplo 18
tiros = 100 If (tiros>0) Print "ATIRANDO!" WaitKey

Estamos criando um loop do tipo While-Wend. Tudo que estiver entre o While e o Wend vai executar de forma indefinida enquanto a condio do While for verdadeira. A condio que colocamos foi (tiros > 0) o que quer dizer, "enquanto tivermos tiros disponveis", isso , enquanto a varivel tiros for maior que zero, o loop executar e todos os comandos dentro dele tambm.
While (tiros > 0)

Toda vez que o loop fizer um ciclo, sorteamos uma posio x e y para onde o tiro dever ser disparado.
SeedRnd MilliSecs() x = Rnd(10,390) y = Rnd(10,290)

Bom, lgico que em um jogo a coisa bem mais complexa. Para dar um tiro, primeiro verificamos se existe munio disponvel, efetuamos o disparo e diminumos em um a quantidade de munio. O programa abaixo dispara tiros aleatrios na tela, enquanto houver balas. Exemplo 19
Graphics 400, 300 tiros = 10 Text 10, 10, "Aperte Space para disparar!" Color 255, 0, 0 While (tiros > 0) SeedRnd MilliSecs() x = Rnd(10,390) y = Rnd(10,290) If KeyHit(57) Plot x,y : tiros = tiros - 1 Wend Cls Color 255, 255, 255

Mas o tiro s ser disparado se a tecla barra de espaos for pressionada (tecla 57). O comando KeyHit verifica se uma tecla foi pressionada; retorna verdadeiro caso tenha sido e falso caso no tenha sido pressionada. Veja que aproveitamos a mesma linha, a mesma condio If para efetuar duas operaes. Primeiro exibimos o tiro, Plot x,y ; depois debitamos o tiro disparado do nosso estoque de munio tiros = tiros - 1. Isso foi possvel graas ao operador ":" que possibilita colocarmos dois ou mais comandos em uma mesma linha.
If KeyHit(57) Plot x,y : tiros = tiros - 1

Depois de dispararmos o dcimo tiro, a varivel tiros ficar igual a zero e a condio para o loop While (tiros > 0) no mais ser satisfeita. Assim sairemos do loop e o processamento seguir pelas linhas abaixo. A tela ser limpa Cls, mudamos a cor da paleta de desenho para branca novamente Color 255, 255, 255, e por fim anunciamos que acabaram os tiros.
Cls

Color 255, 255, 255 Print "Acabaram os tiros"

Print "Vida depois do Ataque de Magia Negra: " + UnidadeVida WaitKey

Operador menor que Verifica se uma varivel ou valor menor que outro. implementado pelo operador <. O uso desse operador semelhante ao anterior, por isso dispensa maiores detalhes. Podemos por exemplo, verificar se a vida menor que 1, ao invs de verificar se igual a zero. Exemplo 20
vida = 10 If (vida<1) Print "To morto!" If (vida>0) Print "To vivo!" WaitKey

Faa um teste, mude o tipo de unidade para "Paladino" e verifique que ele no sofrer o ataque. Operador maior ou igual Esse operador responsvel por verificar se um valor ou varivel maior ou igual a outro. Ambas as situaes do resultado positivo: tanto se for maior como se for igual. Ele implementado por >=. Exemplo 22
a=3 If (a>=2) Print "A maior que 2" If (a>=3) Print "A igual a 3" WaitKey

Operador diferente de O operador diferente de verifica se duas variveis ou valores so diferentes. Ele implementado no Blitz3D por meio do operando <>. O operador diferente tem uma funo muito importante; enquanto o operador de igualdade totalmente exclusivo, isso , realiza algo se somente um nico caso for verdadeiro, ele faz o contrrio, somente um caso no preenche sua satisfao. Isso em lgica se daria assim: Igualdade -> somente uma chave abre uma porta Diferena -> todos podem tomar leite, menos os intolerantes lactose. Existem diversas situaes em jogos que necessitaramos desse operador. Imagine por exemplo que voc criou um jogo onde existem diversos tipos de seres e eles possuem diversos tipos de poderes. Alguns seres tem imunidade sobre alguns poderes. Por exemplo, um Paladino, por ser um cavaleiro sagrado, ele possui a beno de Deus e por isso os ataques de magia negra no o afetaro. Assim para que um ataque de magia negra provoque dano, o tipo da unidade deve ser diferente de paladino. Exemplo 21
UnidadeTipo$ = "Elfo" UnidadeVida = 100 AtaqueMagiaNegra = 33 If (UnidadeTipo$<>"Paladino") UnidadeVida = UnidadeVida - AtaqueMagiaNegra

Operador menor ou igual Semelhante ao maior ou igual, mas nesse caso o teste se menor ou igual. Sua implementao se d por <=. Os bancos ficam atentos a essa situao. Se o seu crdito acabou ou est negativo. Nos dois casos, se for igual a zero ou se for menor que zero, ser enviada uma notificao. Exemplo 23
ClienteA_saldo = -100 ClienteB_saldo = 0 If (ClienteA_saldo<=0) Print "Notificar falta de crdito para Cliente A" If (ClienteB_saldo<=0) Print "Notificar falta de crdito para Cliente B" WaitKey

CONDICIONAIS Vamos fazer agora um estudo mais profundo sobre condicionais. Veremos as outras formas com que o condicional If pode se compor para gerar estruturas mais complexas e eficazes de seleo. Tambm vamos fazer um estudo sobre o condicional Select Case. Outras faces do If O comando condicional If tambm pode ser usado para controlar um bloco de cdigo que s ser executado se esse condicional for
7

verdadeiro. Para isso usamos esse comando junto ao seu auxiliar EndIf. O comando If marca o incio do bloco de cdigo condicional e o EndIf marca o seu termino. Assim, tudo que estiver entre os dois comandos vai ser executado se a condio for verdadeira. No exemplo abaixo, o jogador perdeu todas as suas vidas, portanto o jogo ir ser encerrado. Encerrar um jogo ativa uma srie de coisas, como, exibir mensagem de sada, gravar escores, exibir status final, etc. Tudo pode se ativado por apenas um condicional If em conjunto com o comando EndIf para criar um bloco de cdigo condicional. Para exemplificar isso usamos comandos Print que exibem mensagens desses passos lgicos, mas em um jogo chamaramos funes para concretizar esses passos. Exemplo 24
vidas = 0 If vidas=0 Print "Voc est morto" Print "Gravando Scores" Print "Encerrando a aplicao" EndIf WaitKey

possvel compor estruturas lgicas ainda mais complexas por meio de vrios comandos If aninhados. Aninhar um If colocar um dentro do outro, podendo, assim, serem feitas selees mais precisas. Imagine uma situao em um jogo em que para passar de fase so necessrias duas condies. A primeira delas que o monstro tenha sido derrotado e a segunda que voc tenha a chave para abrir a porta. Exemplo 26
monstro1$ = "ok" chave1$ = "ok" If monstro1$ = "ok" If chave1$ = "ok" Print "Passou de Fase!" Else Print "Falta Pegar a Chave!" EndIf Else Print "volte e mate o monstro!" EndIf WaitKey Teste 1: mude chave1$ = "ok" para chave1$ = "" e

Outra estrutura lgica que podemos compor com o If de construir uma situao onde executado um comando, ou bloco de cdigo, se a verificao for verdadeira e outro comando, ou bloco de cdigo, se a condio for falsa. Para isso fazemos uso do seu auxiliar Else, que significa caso contrrio. Abaixo, uma porta s vai se abrir se tivermos a chave (Chave1 = 1), caso contrrio, ser exibida uma mensagem de que precisamos pegar a chave. Exemplo 25
Chave1 = 0 If Chave1 = 1 Print "Abrindo a Porta!" Else Print "Voc precisa pegar a chave!" EndIf WaitKey No exemplo acima, mude Chave1 = 0 para Chave1 = 1 e veja o resultado.

veja o resultado. Teste 2: mude monstro1$ = "ok" para monstro1$ = "" e veja o resultado.

Cuidado com o uso excessivo ou incorreto de If. Devem ser evitados testes desnecessrios, e criao de muitos Ifs aninhados pois alm de deixar o cdigo mais lento, pode ser mais propcio a erros. A condio com maior propenso a ser verdadeira deve ser a primeira a ser testada para maximizar a performance de seu algoritmo. Procure sempre a soluo mais simples. Select Case Esse comando de seleo excelente para evitar uma srie de Ifs, ou Ifs aninhados. Ele deixa sua estrutura mais compreensvel e o algoritmo mais rpido. O Comando Select registra qual varivel ou condio dever ser testada. O comando Case testa o contedo da varivel para ver se igual ao seu caso. Assim, a estrutura Select-Case se d assim.
8

If aninhado

Select varivel a ser testada Case valor testado Comando A grande vantagem desse comando poder testar vrios casos (case) para uma mesma varivel e s ser executado o case que for verdadeiro, isso , o case que seu valor corresponder ao valor atual da varivel testada. Esse comando muito importante para criar programao genrica, isso , um mesmo cdigo que seja executado por diversas entidades diferentes ou possa ser usado em diversas situaes. Imagine um jogo que seja disponvel para o usurio escolher jogar com um dos 5 tipos de seres diferentes: soldado, mago, bruxo, elfo e ogro. Como eles possuem muita coisa em comum, no seria prudente criar uma funo para cada um, ou um classe para cada um deles. Criamos, por exemplo uma s funo de ataque, e por meio do Select Case, diferimos o ataque correto para cada entidade. Veja abaixo. Exemplo 27
Heroy_Tipo$ = "Ogro" Select Heroy_Tipo$ Case "Soldado" Print "Disparando Tiro" Case "Mago" Print "Usando ataque de fogo" Case "Bruxo" Print "Invocando Devil Summon" Case "Elfo" Print "Disparando Flexa" Case "Ogro" Print "Golpe com Clava" End Select WaitKey

case sejam validados, o comando padro executa. Para isso usamos o Default. Exemplo 28
Pessoa_Tipo$ = "Normal" Select Pessoa_Tipo$ Case "Vegetariano" Print "No Come Carne" Case "Judeo" Print "No come carne de porco" Default Print "Come de Tudo" End Select WaitKey

O exemplo acima demonstra com perfeio a potencialidade dessa estrutura. Devemos criar Case para casos especficos e criar um Default para o comportamento padro. Veja que o comportamento alimentar padro da maioria das pessoas comer de tudo. Alguns grupos minoritrios possuem certas restries alimentares e para eles criamos cases especficos. Lembre-se, Default significa "padro" e case, "caso", criando j a idia de casos especficos frente a um comportamento padro. OPERADORES LGICOS Os operadores lgicos so capazes de modificar ou combinar operadores relacionais. Assim eles so capazes de construir estruturas lgicas extremamente complexas ou criar relaes que um compilador no possui primitivamente. Os principais operadores lgicos so NOT, AND, OR e XOR que em portugus equivalem a no, e, ou e ou exclusivo. Operador Not Esse operador capaz de inverter os valores verdadeiro e falso de uma operao, valor ou varivel. Lembre-se que verdadeiro todo valor diferente de zero e falso igual a zero. Exemplo 29
a=0 b = 100 Print "valor de a: " + a Print "valor de Not a: " + (Not a) Print "valor de b: " + b Print "valor de Not b: " + (Not b) WaitKey

Mude a linha que define o tipo de unidade atual Heroy_Tipo$ = "Ogro" e defina o heroi como "Soldado", "Mago", "Bruxo" ou "Elfo". Veja que com o auxlio dessa estrutura, cada unidade dispara o seu golpe especfico. Como podemos ver, a estrutura Select Case se inicia com Select e termina em End Select. Esse ltimo comando define onde termina a estrutura de seleo. Alm de disparar eventos para cada caso em particular, o Select Case tambm capaz de suportar uma condio padro. Caso nenhum dos
9

Como o valor de a era igual a zero, que igual a falso, o Not transformou o mesmo em 1, isso , verdadeiro. Todo valor diferente de zero verdadeiro. Ao perceber que o valor de b era 100, o operador Not o entende como verdadeiro e o transforma em falso, isso , 0. Os principais usos do operador not so: inverter a verificao de uma condio e criar chaves de tipo liga-desliga. Em Blitz3D voc vai se cansar de ver um caso de inverso de verificao, como do tradicional loop While com fuga em Esc. Esse loop vai executar enquanto a tecla Esc no for pressionada, pois sua condio "enquanto a tecla 1 no for pressionada". Exemplo 30
While Not KeyHit(1) Print "Loop Executando" Wend End

a=1 b=2 If (a=1) And (b=2) Print "Ambas so verdadeiras" Else Print "No passou no teste" EndIf WaitKey

Teste: mude os valores de a e b e verifique que a condio no satisfeita. O operador And, dessa forma, se consolida como um importante recurso para construir a IA (inteligncia artificial) de jogos, afinal e d a possibilidade de criar verificaes e raciocnios mais complexos. Imaginemos uma situao onde, para passar de fase no jogo, deveramos ter realizado uma misso (missao1) e termos derrotado o chefe da fase (chefe1). Essa dupla condio poderia ser verificada de maneira mais simples assim: Exemplo 33
Missao1$ = "OK" Chefe1$ = "OK" If (Missao1$ = "OK") And (Chefe1$ = "OK") Print "Entrando na fase 2..." Else Print "Mate o chefe e conclua a misso" EndIf WaitKey

Nosso prximo exemplo mostra como criar uma chave liga-desliga. Veja que ao pressionarmos a barra de espao If KeyHit(57) a chave invertida pelo operador not chave = Not chave. Exemplo 31
chave = 0 While Not KeyHit(1) Cls Text 100, 100, "Pressione Space mudar Chave" If KeyHit(57) chave = Not chave If chave Text 140, 140, "Chave Ligada" Else Text 140, 140, "Chave Desligada" EndIf Flip Wend End

Veja que passamos a fase, pois as duas condies so verdadeiras, mas experimente mudar as seguintes variveis: 1 teste: mude Missao1$ = "OK" para Missao1$ = "". 2 teste: mude Chefe1$ = "OK" para Chefe1$ = "". Entendendo o operador And A tabela abaixo mostra os resultados para cada combinao com o operador And. Como podemos ver, s ter resultado final verdadeiro (true) se os dois argumentos (condio) forem verdadeiros. Condio 1 Operador Condio 2 RESULTADO
verdadeiro verdadeiro falso falso And And And And verdadeiro falso verdadeiro falso VERDADEIRO FALSO FALSO FALSO

Operador And Esse operador capaz de criar uma dupla condio, isso , para que um comando seja executado, duas condies tero que ser verdadeiras. Seria o mesmo que criar uma estrutura de If aninhado. Se alguma das condies forem falsas ou ambas forem falsas, o And vai retornar falso. Exemplo 32
10

Um outro uso muito comum para esse operador criar ataques especiais, com combinao de teclas. Por exemplo, a tecla "Z"(44) dispara o ataque 1 e a tecla "X"(45) dispara o ataque 2, mas

se pressionarmos as duas ao mesmo tempo, disparamos o ataque especial. Exemplo 34


While Not KeyHit(1) golpe1 = 0 golpe2 = 0 golpe3 = 0 If KeyDown(44) golpe1 = 1 If KeyDown(45) golpe2 = 1 If (golpe1 = 1) And (golpe2 = 1) golpe1 = 0 golpe2 = 0 golpe3 = 1 EndIf If (golpe1 = 1) Print "Deferindo Golpe1!" If (golpe2 = 1) Print "Deferindo Golpe2!" If (golpe3 = 1) Print "Deferindo Golpe Especial!" Wend

tecla ou forma de controle para disparar um tiro. No exemplo abaixo, tanto a tecla barra de espaos (57) quanto a tecla enter (28) disparam o tiro. Exemplo 36
While Not KeyHit(1) If KeyHit(57) Or KeyHit(28) Print "Disparando Missel!" Wend WaitKey

Operador Xor O operador Xor cria uma anlise disjuntiva onde apenas uma das condies deve ser verdadeira para que o resultado da expresso seja verdadeiro. Caso as duas condies sejam verdadeiras, dar falso. Caso nenhuma seja verdadeira, tambm ser falso. Exemplo 37
a=1 b=2 If (a=1) Xor (b=0) Print "S a primeira verdadeira e passou no teste" If (a=0) Xor (b=2) Print "S a segunda verdadeira e passou no teste" If (a=1) Xor (b=2) Print "Ambas verdadeiras, isso no imprime" If (a=0) Xor (b=0) Print "Ambas falsas, isso no imprime" WaitKey

Operador Or Com o operador Or ns podemos criar uma expresso onde apenas um dos elementos precisa ser verdadeiro para que a expresso toda seja verdadeira. Se ambos forem verdadeiros, o resultado tambm verdadeiro. Para que no passe no teste, os dois elementos da expresso devem ser falsos. Exemplo 35
a=1 b=2 If (a=1) Or (b=0) Print "S a primeira verdadeira e passou no teste" If (a=0) Or (b=2) Print "S a segunda verdadeira e passou no teste" If (a=1) Or (b=2) Print "Ambas verdadeiras e passou no teste" If (a=0) Or (b=0) Print "Ambas falsas, isso no imprime" WaitKey

Veja a tabela lgica desse operador. Se os duas condies forem verdadeiras ele dar falso. Condio 1 Operador Condio 2 RESULTADO
verdadeiro verdadeiro falso falso Xor Xor Xor Xor verdadeiro falso verdadeiro falso FALSO VERDADEIRO VERDADEIRO FALSO

Veja a tabela de operaes lgicas para o operador Or. Perceba que para termos um resultado falso necessrio que as duas condies sejam falsas.
Condio 1 verdadeiro verdadeiro falso falso Operador Or Or Or Or Condio 2 verdadeiro falso verdadeiro falso RESULTADO VERDADEIRO VERDADEIRO VERDADEIRO FALSO

Esse operador muito til para criar inteligncia artificial e tambm para controles. Voc pode utiliz-lo por exemplo para definir mais de uma
11

Embora esse operador seja muito usado em operaes lgicas e em matemtica, ser muito difcil voc achar um uso para ele em jogo. Mas vamos tentar usar um pouco a imaginao... Em seu jogo de RPG voc discpulo de um mago. Ele te envia para um misso e diz "V at a caverna encantada. L voc vai encontrar duas gemas mgicas, escolha apenas uma delas!". Assim se voc pegar apenas uma delas, voc passou no teste, se no pegar nenhuma ou pegar as duas, voc est frito. Exemplo 38

GemaVermelha = 1 GemaVerde = 1 If (GemaVermelha = 1) Xor (GemaVerde = 1) Print "Voc est pronto para a prxima tarefa!" Else Print "Teimoso, vai acabar virando um sapo!" EndIf WaitKey

LOOPS Os loops, tambm conhecidos como laos, so estruturas que criam repeties. Eles so usados para diversas finalidades como fazer clculo de incremento, controlar vrios dados ou objetos de uma mesma famlia, ou at manipulao e exibio de cenrios complexos de jogos. For Next Os laos desse tipo so ideais para criar contadores ou estrutura de controle com repeties pr-determinadas. Por meio dele podemos definir na prpria estrutura do lao quantas vezes o mesmo vai ser repetido. O exemplo abaixo exibe 50 vezes o valor de x na tela. Como a varivel vai sendo incrementada, o seu valor vai aumentando. Exemplo 39
For x = 1 To 50 Print "O valor de x : " + x Next WaitKey

Esse comando diz onde o final do bloco de cdigo que deve ser executado dentro do loop. Ao se deparar com esse comando, o programa volta para o cabealho do loop, incrementa a varivel e verifica se chegou ao valor limite, se no chegou executa o cdigo novamente. Se chegou, vai para a linha de cdigo posterior ao Next. No exemplo abaixo, usamos o auxiliar Step de ForNext para especificar de quanto ser o incremento em cada iterao do loop. Como estabelecemos Step 5 ento nossa varivel x vai aumentar de 5 em 5: 1, 6, 11, 16 ... 46. Exemplo 40
For x = 1 To 50 Step 5 Print "------------------------" Print " O valor de x : " + x Next WaitKey

No exemplo abaixo criamos dois loops, sendo que um deles aninhado. Estamos usando essa estrutura para a criao de mapas de cenrio. Nosso exemplo bem simples e estamos usando apenas uma imagem (tile) para compor o mapa. Exemplo 41
Graphics 800,600 tile = LoadImage("midia/agua.png") For y = 0 To 500 Step 100 For x = 0 To 700 Step 100 DrawImage tile, x, y Next Next WaitKey

Nesse exemplo declaramos que a varivel do contador ser a varivel x, tambm dizemos que ela deve ser iniciada a partir do valor 1, pois x = 1. Na estrutura do lao tambm devemos dizer at que ponto o lao vai executar e para isso usamos o comando To. Nesse exemplo declaramos que o lao executar at que a varivel x seja igual a 50, por meio dessa declarao: To 50.
For x = 1 To 50

Como nesse programa estamos pela primeiro vez trabalhando com imagens, vamos dar uma pequena introduo sobre esse assunto, que ser tratado de forma mais rigorosa mais a frente.
tile = LoadImage("midia/agua.png") O comando LoadImage carrega uma imagem do

Essa linha toda poderia ser traduzida por Faa x igual a 1 e execute o loop at que x seja igual a 50. Como no declaramos o valor de incremento, ele ser feito de 1 em 1. Portanto esse linha faz com que o loop seja executado 50 vezes.
Next

disco rgido (ou de cd ou disquete) para uma varivel.Veja que nossa imagem est na pasta "midia" por isso colocamos o operador de escopo. Se a imagem estivesse na mesma pasta do programa, no precisaramos passar sua localizao.
12

Nesse exemplo, estamos carregando a imagem agua.png que est pasta midia para a varivel tile. S depois de carregarmos uma imagem podemos realizar operaes com ela. A partir de agora aquela imagem vai ser invocada por meio da varivel tile.
DrawImage tile, x, y

WaitKey

No nosso exemplo s usamos a imagem para uma finalidade, exibir a mesma na tela. Fazemos isso com o comando DrawImage. Esse comando exibe uma imagem contida em uma varivel em uma posio x, y da tela. Veja que estamos usando as variveis x, y para dizer onde a imagem ser exibida.
For y = 0 To 500 Step 100 For x = 0 To 700 Step 100 DrawImage tile, x, y Next Next

Perceba que como esse tipo de lao de verificao de condio, o incremento tem que ser feito manualmente, dentro do loop. Fizemos a seguinte verificao como condio Enquanto x for menor que 51. Um dos principais usos desse tipo de lao criar loops de controle para capturar eventos. Assim so muito usados em programas interativos, como multimdia, menus e jogos. Veja um exemplo muito usado em jogos do Blitz3D, enquanto a tecla ESC no for pressionada, o loop do jogo fica em execuo. Exemplo 43
While Not KeyHit(1) Print "-*- Jogo em Execuo -*-" Wend End

Veja que criamos 2 loops. Um com a varivel y e outro com a x. Como vamos usar uma imagem de 100 x 100 para compor o cenrio, nossos loops so incrementados de 100 em 100 Step 100. O loop y cuida de incrementar a posio y em que a imagem ser exibida e o loop x a posio x. Como a nossa tela tem 800 de largura, temos que, de 0 a 700 de 100 em 100, existem 8 unidades (0,100,200,300,400,500,600,700) e como nosso tile tem 100 de largura, assim 100 x 8 = 800. Logo, toda a tela recoberta na horizontal. A tela tem 600 de altura, temos que, de 0 a 500 de 100 em 100, existem 6 unidades (0,100,200,300,400,500) e como nosso tile tem 100 de altura, assim 100 x 6 = 600. Logo, toda a tela recoberta no sentido vertical. Loop While O lao do tipo While cria uma repetio de tempo indefinido, enquanto uma condio for satisfeita. Assim, sua estrutura (While condio Wend). O Wend o seu comando de retorno do loop. No exemplo abaixo, criamos uma estrutura While que pode substituir um loop For-Next. Exemplo 42
While (x < 51) Print "------------------------" Print " O valor de x : " + x x=x+1 Wend

No exemplo abaixo, criamos um simples programa de desenho. Usamos um loop While para capturar eventos. A barra de espaos sorteia a cor da paleta de desenho e as setas direcionais movem o pincel. Exemplo 44
Graphics 640, 480 x = 320 y = 240 While Not KeyHit(1) If KeyHit(57) SeedRnd MilliSecs() r = Rnd(0,255) g = Rnd(0,255) b = Rnd(0,255) Color r, g, b EndIf If KeyHit(205) x = x + 1 If KeyHit(203) x = x - 1 If KeyHit(208) y = y + 1 If KeyHit(200) y = y - 1 Plot x, y Wend End

A lgica do programa usar o loop para poder rastrear eventos do teclado. As setas direcionais alteram as posies x e y onde o ponto exibido e a tecla barra de espao sorteia uma nova cor para a paleta de desenho.
13

Abaixo temos um exemplo no funcional do uso do loop While para implementar a arquitetura de um jogo. Dentro do loop do jogo colocamos chamadas das funes de controle do jogo, que devero ser declaradas mais abaixo, logo depois do comando End. Em breve explicaremos como usar funes. While Not KeyHit(1) Verificar_Entradas() Processar_Logica() Processar_Fisica() Renderizar() Wend End Repeat Until Esse tipo de lao garante que o bloco de cdigo vai executar pelo menos uma vez, mesmo que a condio seja falsa ou verdadeira. Bem por isso o teste de condio se d no final do bloco, no comando Until. Veja um exemplo onde ele s executa uma vez. Exemplo 45
x=0 Repeat Print "-*- Jogo em Execuo -*-" Until x = 0 WaitKey End

FUNES Dentro do ambiente de desenvolvimento do Blitz3D as funes so as estruturas mais elaboradas para projetar o seu software de forma a prover reuso de cdigo, organizao e modularidade ao mesmo. As principais caractersticas de uma funo so: capacidade de passar argumentos, capacidade de retornar dados e controle de escopo. Por meio dessas caractersticas as funes so capazes de tornar-se uma estrutura de cdigo autosuficiente, independente de outros trechos do programa. Em uma arquitetura perfeita de software no Blitz3D, uma funo deve ser projetada e usada de forma a manter um nico canal de dependncia: a sua prpria invocao. Isso garante que o cdigo eficiente, fcil de ser testado, de manuteno simples, fcil de ser modificado e poder ser reutilizado em outros projetos. Um exemplo mnimo Vamos dar um exemplo de uma funo mais simples possvel e seu uso. Os elementos essenciais de uma funo so: sua declarao, seu bloco de cdigo e sua invocao. Exemplo 47
exibe() WaitKey End Function exibe() Print "funciona!" End Function

O significado de Until at, portanto ele executa at que a condio seja verdadeira. Isso inverte a lgica do While, que executa enquanto a condio for verdadeira. Por isso que no exemplo acima, mesmo a condio sendo verdadeira, s executa uma vez. No exemplo a segui criamos um loop que se encerra com o apertar da tecla ESC. Mas perceba que, como a lgica de execuo inversa do While, aqui no fizemos uso do operador lgico Not (Not KeyHit(1)), pois agora o loop executa at que a tecla 1 seja pressionada. Exemplo 46
Repeat Print "-*- Jogo em Execuo -*-" Until KeyHit(1) End

Vamos a linha que declara a funo:


Function exibe() O comando Function instrui ao Blitz3D que vamos

declarar uma funo, o passo seguinte dar um nome para a funo, nesse caso escolhemos o nome exibe pois vamos exibir uma mensagem. O nome deve sempre ser finalizado por um par de parnteses "()" que a rea de argumentos de uma funo. Como essa funo simples, no recebe argumentos, por isso os parnteses esto vazios.
Print "funciona!"

14

O passo seguinte declarar o bloco de cdigo que deve executar quando a funo invocada. No nosso exemplo colocamos apenas uma linha, mas poderiam ser milhes.
End Function

Devemos dizer ao Blitz3D onde se encerra a declarao da funo e isso se d com a declarao End Function.
exibe()

funes e cada funo responsvel por fazer sua parte do trabalho de composio da aplicao. Nossa funo de Controle responsvel pelos controles na nave e a funo Draw, responsvel por exibir a imagem na tela. Mais para a frente vamos incrementar esse programa e voc ter uma idia mais completa da estrutura de um jogo e suas funcionalidades. Passando Dados As funes so capazes de receber dados (argumentos) de quem as invoca, para serem usados no corpo da funo. possvel declarar no cabealho da funo quais os tipos de argumentos que essa funo aceita. Podemos declarar desde que no suportar nenhum, como no exemplo anterior, ou que suportar apenas um tipo especfico (isso , um int, um float ou uma string), ou tambm podemos declar-la para suportar vrios argumentos. Vamos analisar cada caso. Passando parmetros inteiros Para que uma funo possa aceitar um dado do tipo inteiro ela deve possuir uma varivel de inteiros no cabealho de sua declarao. Lembrese que inteiro so variveis com ausncia de sufixos ou ento com sufixo "%" A funo de exemplo abaixo exibe o quadrado de um nmero e suporta apenas nmeros inteiros. Caso voc no se recorde, o quadrado de um nmero o numero resultante da multiplicao desse nmero por ele mesmo. Exemplo 49
calcula(3) WaitKey End Function calcula(numero) Print "O quadrado : " + ( numero * numero) End Function

Para usar uma funo devemos chamar pelo seu nome. Como nesse exemplo nossa funo no suporta argumentos, chamamos a funo com os parnteses vazios. Usando Funes em Jogos Se as funes no existissem, nossos jogos seriam uma massa contnua e desorganizada de cdigo. Provavelmente muitas partes do cdigo dependeriam de muitas outras e seria muito difcil compreender, alterar e fazer manuteno no cdigo. Reuso ento, impensvel. Por meio das funes podemos criar blocos lgicos de cdigo com finalidades especficas. Cada bloco de cdigo tem uma responsabilidade prpria e funciona de maneira bastante autnoma. Vamos ver como isso funciona na prtica em um jogo. Exemplo 48
Graphics 800, 600 SetBuffer BackBuffer() Global nave = LoadImage("midia/f15.bmp") Global px = 380 Global py = 450 While Not KeyHit(1) Controle() Draw() Wend End Function Controle() If KeyDown(203) px = px - 1 If KeyDown(205) px = px + 1 End Function Function Draw() DrawImage nave, px, py Flip Cls End Function

A primeira coisa que fizemos foi declara a funo


Function calcula(numero)

Veja que agora o cdigo est bem estruturado. Dentro o loop fazemos apenas invocaes s
15

Declaramos uma funo de nome calcula, perceba que ela possui uma varivel dentro dos parnteses numero. Essa varivel no possui sufixo, portanto de inteiros.
Print "O quadrado : " + ( numero * numero)

No bloco de cdigo estamos recuperando o valor da varivel do cabealho da funo na operao de multiplicao (numero * numero). assim que funciona o mecanismo de operaes abstratas de uma funo. Declaramos uma varivel genrica e a mesma pode receber qualquer dado do tipo dela. Dai recuperamos a varivel dentro da funo e fazemos operaes com ela. Assim criamos um mecanismo abstrato capaz de fazer operaes com qualquer tipo de dados, basta passar o que queremos calcular.
calcula(3)

Nessa linha temo o exemplo do uso da funo. Invocamos a mesma pelo seu nome e passamos para ela o valor que desejamos que ela calcule. Como o valor um inteiro, portanto corresponde ao tipo estabelecido, ela aceita como valor para a varivel do cabealho da funo e opera com ele em seu interior. Veja no exemplo a seguir vrios usos da funo criada. Exemplo 50
calcula(1) calcula(7) calcula(111) WaitKey End Function calcula(numero) Print "O quadrado : " + ( numero * numero) End Function

Global HeroiVida = 100 ;tiro1 disparado tiro1 = 1 ;tiro2 disparado tiro2 = 1 ;item1 coletado item1 = 1 ;item2 coletado item2 = 1 If tiro1 SetVida(-20) If tiro2 SetVida(-50) If item1 SetVida(10) If item2 SetVida(25) WaitKey End Function SetVida(Valor) HeroiVida = HeroiVida + Valor Print "A vida do Heroi : " + HeroiVida End Function

Nesse programa usei uma simples atribuio para representar um evento de colises:
tiro1 = 1 item1 = 1

Em um jogo, os eventos receber um tiro ou pegar um item so disparado por uma coliso, mas isso ficaria muito complexo para esse momento.
If tiro1 SetVida(-20) If tiro2 SetVida(-50) If item1 SetVida(10) If item2 SetVida(25)

Usando passagem de argumentos em jogos O real poder das funes est no fato de elas poderem passar argumentos, dessa forma podemos criar apenas uma funo para efetuar diversas trabalhos diferentes. Imagine uma situao onde, em um jogo de tiro, o personagem perde vira ao receber um tiro ou um golpe e ganha vida ao coletar itens, mas cada tiro ou golpe tira quantidades diferentes de vida, afinal existem armas diferentes... E, cada item tambm restaura quantidades diferentes de vida. Tudo isso parece muito complexo, mas pode ser implementado apenas por uma funo que aceite um nico parmetro. Uma funo SetVida(valor). Vamos prtica. Exemplo 51
16

Nessas linhas verificamos se o evento foi disparado, isso , se fomos atingidos pelo tiro ou se pegamos o item. Caso seja verdadeiro, acionamos a funo de configurao de vida e passamos a ela a quantidade de vida que cada evento tiro ou item resulta. Passando parmetros do tipo float Como voc se lembra, uma varivel de inteiros no suporta um valor de ponto flutuante, assim ele ser arredondado. O mesmo se d com parmetros de funes. Veja, no exemplo abaixo, o que ocorre se passarmos um nmero decimal para uma funo de inteiros. Exemplo 52
calcula(1.8) WaitKey End Function calcula(numero) Print "O quadrado : " + ( numero * numero) End Function

Para evitar que ocorram arredondamentos desse tipo em funes que podem, por ventura, receber um parmetro de ponto flutuante, necessrio que declaremos uma funo como receptora de argumentos do tipo float. Para isso, em seu cabealho devemos colocar variveis do tipo float, com o sufixo Sharp #. Vamos a uma nova verso do programa acima. Exemplo 53
calcula(1.8) WaitKey End Function calcula(numero#) Print "O quadrado : " + ( numero# * numero#) End Function

Passando vrios parmetros Teoricamente, voc pode criar funes com suporte a uma quantidade ilimitada de argumentos. E voc pode colocar tipos diferentes de argumentos misturados. Veja no exemplo abaixo uma funo que aceita vrios inteiros para som-los depois. Exemplo 56
soma(1, 10, 5, 333, 1028) WaitKey End Function soma(a,b,c,d,e) Print "O resultado : " + (a+b+c+d+e) End Function

Agora sim ela funciona corretamente. Passando textos para funes Para que uma funo aceite argumentos em forma de texto essa deve ter em seu cabealho uma varivel de string, com sufixo dlar $. Veja no exemplo abaixo uma funo que suporte argumentos em texto. Exemplo 54
exibe("Blitz3D Legal") exibe("Eu amo Blitz3D") WaitKey End Function exibe(texto$) Print "---------------------------------------------" Print "-------------- " + texto$ + " --------------" Print "---------------------------------------------" End Function

Veja agora o exemplo de uma funo que aceita os trs tipos diferentes de argumentos. Dois inteiros que devero dizer em que local da tela a mensagem ir ser exibida. Um texto com o nome e um float com a mdia da nota do aluno. Exemplo 57
aluno(100,100,"Daniel", 9.5) WaitKey End Function aluno(x,y,nome$,nota#) Text x,y, "Nome:" + nome$ + " " + "Nota:" + nota# End Function

Voc provavelmente vai usar uma funo que necessite receber dados em strings para criar seu sistema de escores e fazer login e para trocar mensagens em um jogo multiplay. Exemplo 55
Print "------------ enviar mensagem ------------" While Not KeyHit(1) Print "" msm$ = Input$("Digite a mensagem: ") msm$ = "JOGADOR1: " + msm$ EnviarMensagem(msm$) Wend End Function EnviarMensagem(M$) Print "-> " + M$ End Function

Retornando dados A segunda caracterstica muito importante das funes a sua capacidade de retornar dados. O fato de ela poder receber e retornar dados que d a ela sua capacidade modular de ser uma unidade de software autnoma. Ela pode ser separada do resto do programa como uma prestadora de servios. Passamos a ela nosso problema (os parmetros) e ela processa e nos d a resposta (retorno de valores). Para que uma funo possa retornar um valor precisamos configurar mais duas coisas nela: devemos dizer qual o tipo de dado que a funo retorna e usar o comando Return para dar a resposta. Funo retornando um inteiro Para que uma funo possa retornar um valor inteiro devemos usar o comando Return. Como ocorre com as variveis, as funes so por
17

padro de inteiros; assim, no necessrio colocar um sufixo de inteiros em uma funo. Vamos fazer isso nesse exemplo apenas para ter idia de como se faz. Exemplo 58
cubo = calcula_cubo%(3) Print cubo WaitKey Function calcula_cubo%(x) Return x*x*x End Function

Function calcula_cubo(x) calc = x*x*x Return calc End Function

Retornar um float Para que uma funo retorne um float necessrio marc-la como uma funo de retorno de floats com o sufixo sharp #. Exemplo 61
divide# = DIV#(10,3) Print divide# WaitKey Function DIV#(x#,y#) calc# = x#/y# Return calc# End Function

Perceba que ao declarar a funo, a declaramos com um sufixo "%" de inteiros.


Function calcula_cubo%(x)

esse sufixo na funo que determina qual o tipo de valor ela vai retornar.
Return x*x*x

O comando Return o que retorna o valor para quem chama. Como queremos que essa funo retorne o cubo do numero passado como argumento, fizemos (x*x*x) isso , o cubo do nmero, pois o cubo um numero multiplicado por ele mesmo duas vezes.
cubo = calcula_cubo%(3)

Retornar uma string Uma funo que pretenda retornar um texto deve possuir em sua definio o sufixo $. Veja um exemplo de uma funo que envia um texto e o recebe de volta com alguns ornamentos. Exemplo 62
texto$ = tratar$("Hoje meu dia de sorte") Print texto$ WaitKey Function tratar$(x$) tratado$ = "|*-*-< " + x$ + " >-*-*|" Return tratado$ End Function

Perceba que na invocao da funo colocamos uma varivel cubo para capturar o valor que ela retorna. Esse o procedimento padro para pegar o valor de retorno de uma funo. Como Dissemos, uma funo sem tipo de retorno definido por padro uma funo de inteiros. Portanto, o exemplo abaixo tambm funciona. Exemplo 59
cubo = calcula_cubo(2) Print cubo WaitKey Function calcula_cubo(x) Return x*x*x End Function

Voc tambm pode colocar o valor dos clculos internos em uma varivel interna e mandar que retorne o valor dessa varivel, o que o procedimento mais comum. Exemplo 60
cubo = calcula_cubo(7) Print cubo WaitKey

Usando retorno de dados em Jogos Vamos dar seqncia quele projeto do joguinho do avio F15. Adicionamos algumas funcionalidades extras: colocamos asterides em movimento pontuao e detectamos colises. O uso de retorno de dados nesse jogo se d na nossa funo de verificao de colises; se algum dos asterides se chocar com a nave, a funo de colises retorna o valor 1 e ento encerramos o jogo.

18

Exemplo 63
Graphics 800, 600 SetBuffer BackBuffer() Global nave = LoadImage("midia/f15.bmp") Global px = 380 Global py = 450 Global pedra1 = LoadImage("midia/pedra1.png") Global p1x = Rnd(0,700) Global p1y = -Rnd(100,700) Global pedra2 = LoadImage("midia/pedra2.png") Global p2x = Rnd(0,700) Global p2y = -Rnd(100,700) Global pedra3 = LoadImage("midia/pedra3.png") Global p3x = Rnd(0,700) Global p3y = -Rnd(100,700) Global pedra4 = LoadImage("midia/pedra1.png") Global p4x = Rnd(0,700) Global p4y = -Rnd(100,700) Global pedra5 = LoadImage("midia/pedra2.png") Global p5x = Rnd(0,700) Global p5y = -Rnd(100,700) Global PONTOS = 0 While Not KeyHit(1) Controle() Fisica() If Colide() Then GameOver() Logica() Draw() Wend End

Function Controle() If KeyDown(203) px = px - 1 If KeyDown(205) px = px + 1 End Function Function Logica() Pontos = Pontos + 1 End Function Function Fisica() p1y = p1y + 3 p2y = p2y + 3 p3y = p3y + 3 p4y = p4y + 3 p5y = p5y + 3 If p1y > 600 p1y = -Rnd(100,500) p1x = Rnd(0,700) EndIf If p2y > 600 p2y = -Rnd(100,500) p2x = Rnd(0,700) EndIf If p3y > 600 p3y = -Rnd(100,500) p3x = Rnd(0,700) EndIf If p4y > 600 p4y = -Rnd(100,500) p4x = Rnd(0,700) EndIf If p5y > 600 p5y = -Rnd(100,500) p5x = Rnd(0,700) EndIf End Function Function Draw() DrawImage nave, px, py DrawImage pedra1, p1x, p1y DrawImage pedra2, p2x, p2y DrawImage pedra3, p3x, p3y DrawImage pedra4, p4x, p4y DrawImage pedra5, p5x, p5y Color 255,0,0 Text 10, 10, "PONTOS: " + PONTOS Flip Cls End Function Function Colide() If ImagesCollide(nave,px,py,0,pedra1,p1x,p1y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra2,p2x,p2y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra3,p3x,p3y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra4,p4x,p4y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra5,p5x,p5y,0) Then Return 1

19

End Function Function GameOver() Cls Text 350, 290, "GAME OVER" Text 310, 310, "Voc fez " + PONTOS + " Pontos" Flip Delay(3000) End End Function

Essa varivel responsvel por controlar a pontuao do jogador.


While Not KeyHit(1) Controle() Fisica() If Colide() Then GameOver() Logica() Draw() Wend End

Explicando...
Graphics 800, 600 SetBuffer BackBuffer()

Nessas duas linhas estamos configurando o modo grfico do jogo. Estamos configurando a tela para rodar em 800 x 600 e estamos ligando o modo de double buffer. Explicaremos melhor isso na parte de grficos 2d.
Global nave = LoadImage("midia/f15.bmp") Global px = 380 Global py = 450

Acima est o nosso loop de controle do jogo. Veja que ele bem estruturado do ponto de vista lgico. Primeiro invocamos a funo de controle, depois a de fsica, em seguida a de Colises, logo aps a de lgica e por ltimo a de desenho. Veja que caso a funo de colises retorne algum valor, a funo GameOver acionada.
Function Controle() If KeyDown(203) px = px - 1 If KeyDown(205) px = px + 1 End Function

Estamos carregando a imagem da nave para a varivel nave e estamos definindo a sua posio inicia no eixo x como 380 e sua posio y como 450. As variveis px e py so responsveis por controlar a posio da nave. Perceba que todas as variveis esto sendo declaradas como Global, isso porque elas sero acessadas de dentro de funes e s variveis globais so reconhecidas dentro de funes.
Global pedra1 = LoadImage("midia/pedra1.png") Global p1x = Rnd(0,700) Global p1y = -Rnd(100,700)

Acima temos nossa funo de controle. Ele verifica se as teclas seta para a esquerda e seta para a direita foram pressionadas. Caso isso seja verdadeiro, movimenta a nave por meio da alterao de suas variveis posicionais.
Function Logica() Pontos = Pontos + 1 End Function

Usamos a mesma estrutura para construir todos os asterides. Carregamos a imagem dele para uma varivel Global (nesse caso a varivel pedra1), definimos uma varivel para controlar a sua posio x (p1x) e uma varivel para a posio y (p1y). Para que os asterides no apaream sempre no mesmo lugar, a sua posio dada por um sorteio de nmero aleatrio Rnd(). Lembre-se de que as pedras descero da parte superior da tela para a parte inferior e como elas tem 100 pixels de tamanho, sua posio inicial y deve ser de pelo menos -100, por isso usamos o sorteio p1y = -Rnd(100, 700), assim sua posio inicial ser de -100 at -700.
Global PONTOS = 0

Nossa funo de lgica no tem segredos. Ela apenas vai contando pontos. Cada vez que o loop faz uma iterao, isso , que ele d uma volta, conta 1 ponto.
Function Fisica() p1y = p1y + 3 p2y = p2y + 3 p3y = p3y + 3 p4y = p4y + 3 p5y = p5y + 3

A primeira parte de nossa funo de fsica apenas movimenta os asterides. Faz isso um por um, alterando o valor da varivel py de cada um deles. Como a varivel vai aumentando, eles vo se movendo da parte superior da tela para a parte inferior.
If p1y > 600 p1y = -Rnd(100,500)

20

p1x = Rnd(0,700) EndIf

A segunda parte da funo de fsica verifica se ele j cruzaram a rea de visibilidade da parte inferior da tela. Se eles j cruzaram esse limite, vo ser reposicionados na parte superior da tela. Assim fazemos o mesmo sorteio que fizemos no inicio do programa. Usando essa tcnica no precisamos ficar criando infinitas instncias de meteoros para o jogo, s cinco objetos deu conta.
Function Draw() DrawImage nave, px, py DrawImage pedra1, p1x, p1y DrawImage pedra2, p2x, p2y DrawImage pedra3, p3x, p3y DrawImage pedra4, p4x, p4y DrawImage pedra5, p5x, p5y Color 255,0,0 Text 10, 10, "PONTOS: " + PONTOS Flip Cls End Function

segunda imagem a ser verificada a imagem pedra1, a posio x dela p1x, a posio y p1y e o frame 0. Assim possvel verificar colises entre nave e pedra1. Veja que se a coliso acontece, acionado Return 1. Esse comando encerra a execuo de uma funo, e retorna um valor. Assim, quando um asteride colidir com a nave, a funo forada a encerrar e retorna o valor 1.
Function GameOver() Cls Text 350, 290, "GAME OVER" Text 310, 310, "Voc fez " + PONTOS + " Pontos" Flip Delay(3000) End End Function

A funo de desenho exibe as imagens na tela. Veja que estamos exibindo a nave, os meteoros e os pontos. O comando Flip atualiza a tela e o comando Cls apaga a exibio para deixar a tela limpa para a prxima composio.
Function Colide() If ImagesCollide(nave,px,py,0,pedra1,p1x,p1y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra2,p2x,p2y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra3,p3x,p3y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra4,p4x,p4y,0) Then Return 1 If ImagesCollide(nave,px,py,0,pedra5,p5x,p5y,0) Then Return 1 End Function

Ai est nossa funo final. Ela limpa a tela e exibe a mensagem de final de jogo e a pontuao do jogador. Por fim ela usa o comando Delay(3000) para fazer com que a imagem permanea na tela por 3000 milsimos de segundos, isso , 3 segundos. O comando Delay() faz o processamento para por um tempo especificado. Viu como foi fcil? Voc j saber o suficiente de programao para fazer jogos bsicos muito bem estruturados! Controle de escopo A terceira caracterstica importante das funes o fato de possuir escopo diferente do resto do cdigo. Assim, variveis externas s funes no so reconhecidas por essa e variveis criadas dentro dela so aniquiladas quando a execuo do cdigo chega em End Function. Exemplo 64
x = 10 Print "X de fora: " + x func() Print "X de fora: " + x WaitKey End Function func() x = 333 Print "X de dentro: " + x End Function

Essa a nossa funo de colises. Veja que a verificao de colises feita por meio do comando ImagesCollide(). Esse comando um pouco complexo mas no difcil. Devemos colocar por seqncia Imagem1, posiox, posioy e frame e para a segunda imagem os mesmos valores. O veja, por exemplo a primeira linha, a primeira imagem da verificao nave, a posio x dada por px e a posio y por py, j o frame 0 pois no uma imagem animada. A
21

Perceba que declaramos o valor de x no cdigo principal com o valor 10 nessa linha:
x = 10

Logo em seguida ordenamos sua exibio.


Print "X de fora: " + x

A exibio confirmou a declarao anterior.


func()

Nessa linha acima, invocamos a funo que possui o segundo corpo de cdigo:
x = 333 Print "X de dentro: " + x

Perceba que estamos criando e definindo o contedo de uma nova varivel local da funo. Essa varivel no tem nada a ver com a varivel x anterior que de escopo do cdigo externo funo. Isso pode ser demonstrado no cdigo a seguir.
Print "X de fora: " + x

de variveis e alterao de valores acidentalmente. Existe uma maneira de voc conseguir burlar essa regra de escopo. Isso pode ser feito por meio de variveis de escopo global. Uma varivel definida como global tem validade em qualquer parte do programa. O prximo exemplo demonstra isso, uma varivel definida como global alterada dentro de uma funo. Exemplo 66
Global x = 100 Print "Fora da Funo x = " + x func() Print "Fora da Funo x = " + x WaitKey End Function func() x = x + 100 Print "Dentro da Funo x = " + x End Function

Essa linha vem aps a invocao da funo e est fora dela. Perceba que a varivel x externa possui o mesmo valor, isso 10 pois a mesma no foi afetada pela declarao interna da funo. Assim, podemos deduzir que as funes possuem cada qual um escopo parte. Cada funo possui escopo prprio diferente do escopo das demais e do escopo do cdigo principal. O exemplo a seguir demonstra que o escopo destrudo toda vez que a funo passa pelo comando End Function, isso , a cada vez que a funo chamada, as variveis so criadas e destrudas. Exemplo 65
func() func() WaitKey End Function func() x = x + 100 Print "O valor de X: " + x End Function

Perceba que a varivel foi reconhecida dentro da funo, pois x + 100 resultou em 200. Veja tambm que esse valor se manteve fora da funo, pois o Print final, que no cdigo principal, tambm exibiu esse valor. Assim, uma varivel global possui escopo universal, isso , valida em qualquer lugar. Garantindo o escopo local Como vimos, por boa prtica devemos usar as funes sempre com escopo local para evitar erros com alteraes inesperadas de valores de variveis. Ocorre que embora seja desaconselhvel manter variveis globais em um programa isso s vezes ocorre por razes diversas. Assim pode ser que acidentalmente acessemos uma delas dentro de uma funo. Para evitar isso, quando declaramos variveis internas de uma funo, uma boa prtica dizer que essa uma varivel local. Isso pode ser feito por meio do comando de controle de escopo Local. Veja um exemplo onde alteramos o cdigo anterior, definindo a varivel x interna da funo como Local. Exemplo 67
Global x = 100

Perceba que as duas invocaes produzem o mesmo resultado: 100. Se a funo conservasse as variveis, na segunda invocao o resultado deveria ser 200. Burlando o escopo A regra de escopo das funes existe para que sejamos obrigados a usar os mecanismos de passagem de dado pelo cabealho e receber o resultado pelo return. Alm disso, esse mecanismo de escopo evita erros de duplicao
22

Print "Fora da Funo x = " + x func() Print "Fora da Funo x = " + x WaitKey End Function func() Local x = x + 100 Print "Dentro da Funo x = " + x End Function

Text soldados\px, soldados\py, soldados\NOME$ WaitKey

Vamos explicar esse programa linha por linha. Em primeiro momento declaramos o type.
Type Tinimigo

4. PROGRAMAO: PARTE II Vamos iniciar agora nosso ltimo bloco de tcnicas de programao. Depois de estudar esse bloco voc ter aprendido os principais recursos das linguagens de programao e estar apto de desenvolver qualquer tipo de jogo. Types Types so tipos de dados compostos que voc mesmo cria e depois de cri-los voc pode criar variveis dele. Como eles so tipos de dados compostos, uma varivel de um type pode conter vrios campos internos como inteiros, strings, floats, etc. A principal vantagem dos types que voc cria modelos de objetos. Por exemplo, um personagem de um jogo possui vrios dados como, uma imagem, uma posio x, uma posio y, vida, dinheiro, fora, armas, etc. Em um type voc pode criar uma estrutura coesa com todos esses dados, sem precisar ficar criando vrias variveis soltas. Depois voc pode criar quantos objetos quiser dessa estrutura. Imagina que em um jogo voc vai ter 1.000 soldados inimigos e cada um deles devem possuir pelo menos 10 variveis de controle. Em vez de criar 10.000 variveis, voc pode criar apenas 1 type com 10 campos. Vamos ao exemplo prtico. Exemplo 1
Type Tinimigo Field px Field py Field NOME$ End Type soldados.Tinimigo = New Tinimigo soldados\px = 100 soldados\py = 100 soldados\NOME$ = "Ogro1"

Estamos declarando que iremos construir um modelo de types. Para isso usamos o comando Type e demos a esse novo modelo o nome Tinimigo.
Field px

Estamos declarando um campo para o type. Para declarar um campo usamos o comando Field que em ingls significa campo. Estamos dando o nome px para esse primeiro campo, pois ele vai guardar a posio x do personagem. Um campo na verdade uma varivel interna do type. Podemos ter quantas variveis internas desejarmos.
Field py

Estamos declarando o nosso segundo campo, para conter a posio y do personagem.


Field NOME$

Estamos, nessa linha, declarando o nosso terceiro e ltimo campo NOME$, que agora do tipo string; portanto dever conter um texto. Vamos usar ele para dar a identidade do objeto.
End Type

Por fim estamos encerrando a declarao do modelo por meio do comando End Type. Os passos seguintes so de como usamos o type.
soldados.Tinimigo = New Tinimigo

Nessa linha estamos declarando uma varivel do type; a varivel soldados. Para declarar uma varivel colocamos o nome da varivel mais o operador ponto ., mais o nome do type, depois o operador de atribuio =, seguido do operador New e o nome do type mais uma vez, assim a forma de declarar :
varivel.type = New type

Depois de j termos uma varivel declarada podemos declarar o contedo de cada campo.
soldados\px = 100

23

Perceba que acessamos o campo px da varivel de type e lhe atribumos o valor 100. Fizemos isso por meio do operador barra invertida \. A sintaxe para o acesso aos campos da varivel do typo :
varivel\campo

WaitKey

O passo seguinte foi continuar a declarar os contedos da varivel.


soldados\py = 100

Aqui declaramos o contedo do campo py.


soldados\NOME$ = "Ogro1"

Listas de objetos Como vimos no exemplo anterior, podemos declarar muitas variveis de um mesmo type. Mas existem situaes em que possumos vrios objetos ou seres de uma mesma natureza. Por exemplo, a varivel soldados; em um jogo real temos at centenas de soldados e no apenas um. Como identificar e tratar todos eles de uma maneira simples e dinmica? O Blitz3D possui um mecanismo interno de listas de objetos de types que permite manipular vrias instncias de uma mesma varivel de tipos. No exemplo declaramos vrias vezes objetos do tipo soldados. Exemplo 3
Type Tinimigo Field px Field py Field NOME$ End Type soldados.Tinimigo = New Tinimigo soldados\px = 170 soldados\py = 100 soldados\NOME$ = "Ogro1" soldados.Tinimigo = New Tinimigo soldados\px = 100 soldados\py = 130 soldados\NOME$ = "Ogro2" soldados.Tinimigo = New Tinimigo soldados\px = 50 soldados\py = 140 soldados\NOME$ = "Ogro3" WaitKey

E por fim o contedo do campo NOME$. Perceba que por ser um campo de strings declaramos como contedo um texto, o nome do objeto.
Text soldados\px, soldados\py, soldados\ID$

J com todos os contedos declarados, podemos utilizar a varivel do type. Na linha acima usamos os campos px e py para dar as coordenadas para o comando text e exibimos o nome do objeto do type que est guardado no campo NOME$. Muitas variveis possvel declarar quantas variveis desejarmos de um mesmo type. No exemplo anterior utilizamos o modelo para criarmos apenas uma varivel, a varivel soldados, mas no existe um limite para quais e quantas podem ser criadas. Veja um novo exemplo. Exemplo 2
Type Tinimigo Field px Field py Field NOME$ End Type soldados.Tinimigo = New Tinimigo soldados\px = 170 soldados\py = 100 soldados\NOME$ = "Ogro1" bicho.Tinimigo = New Tinimigo bicho\px = 50 bicho\py = 130 bicho\NOME$ = "Elefante" pessoa.Tinimigo = New Tinimigo pessoa\px = 140 pessoa\py = 70 pessoa\NOME$ = "Fada" Text soldados\px, soldados\py, soldados\NOME$ Text bicho\px, bicho\py, bicho\NOME$ Text pessoa\px, pessoa\py, pessoa\NOME$

Veja que nesse exemplo declaramos trs vezes a varivel soldados e na verdade no estamos redefinindo a mesma varivel, estamos criando uma lista do tipo soldados com 3 elementos. Acessando dados da lista A maneira mais fcil de acessar os dados de uma lista de objetos de types por meio de um loop do tipo For-Each-Next. Esse tipo de loop detecta automaticamente quantos elementos existem dentro de uma lista e passa por todos eles, um por um. Exemplo 4
Type Tinimigo Field px Field py

24

Field NOME$ End Type soldados.Tinimigo = New Tinimigo soldados\px = 170 soldados\py = 100 soldados\NOME$ = "Ogro1" soldados.Tinimigo = New Tinimigo soldados\px = 100 soldados\py = 130 soldados\NOME$ = "Ogro2" soldados.Tinimigo = New Tinimigo soldados\px = 50 soldados\py = 140 soldados\NOME$ = "Ogro3" For soldados.Tinimigo = Each Tinimigo Text soldados\px, soldados\py, soldados\NOME$ Next WaitKey

soldados\px = 50 soldados\py = 140 soldados\NOME$ = "Ogro3" For soldados.Tinimigo = Each Tinimigo If soldados\NOME$ = "Ogro2" Text soldados\px, soldados\py, soldados\NOME$ EndIf Next WaitKey

Veja que a sintaxe desse tipo de loop bem simples varivel.type = Each type Acessando um objeto especfico em uma lista Para acessar um elemento especfico de uma lista voc pode fazer a busca por algum dado dele, normalmente o seu nome ou sua ID, com a ajuda de um comando de comparao If. Em jogos provavelmente voc tambm dever fazer busca pela posio dele ou por um dado que diga qual sua rea de atuao, pois provavelmente voc deseje usar a IA de inimigos apenas que estejam no mesmo quadrante que o personagem principal do jogo, o qual a cmera segue. Mas independente de como voc ir fazer a identificao o mecanismo o mesmo, um loop For-Each-Next e um comando If. No exemplo abaixo fazemos um busca pelo Ogro2 e s ele ser usado. Exemplo 5
Type Tinimigo Field px Field py Field NOME$ End Type soldados.Tinimigo = New Tinimigo soldados\px = 170 soldados\py = 100 soldados\NOME$ = "Ogro1" soldados.Tinimigo = New Tinimigo soldados\px = 100 soldados\py = 130 soldados\NOME$ = "Ogro2" soldados.Tinimigo = New Tinimigo

claro que em um jogo a estrutura no ser essa. Provavelmente voc ter uma funo apenas para pegar a identidade dos personagens e vrias para tratar o comportamento deles. Ento o exemplo abaixo, que usa estruturas abstratas e reutilizveis o mais correto para um ambiente real de jogo. Exemplo 6
Type Tinimigo Field px Field py Field NOME$ End Type soldados.Tinimigo = New Tinimigo soldados\px = 170 soldados\py = 100 soldados\NOME$ = "Ogro1" soldados.Tinimigo = New Tinimigo soldados\px = 100 soldados\py = 130 soldados\NOME$ = "Ogro2" soldados.Tinimigo = New Tinimigo soldados\px = 50 soldados\py = 140 soldados\NOME$ = "Ogro3" Exibe("Ogro2") WaitKey Function Exibe(identidade$) For soldados.Tinimigo = Each Tinimigo If soldados\NOME$ = identidade$ Text soldados\px, soldados\py, soldados\NOME$ EndIf Next End Function

O mtodo para obter a identidade depende do tipo de jogo e de qual ao est em curso. As vezes poder ser apenas uma localizao geogrfica, no caso de aplicar a IA em soldados inimigos; ou poder ser deteco de colises; poder se o fato de o personagem estar em sua frente em uma situao de dilogo; para abrir uma porta ou ligar um dispositivo. Existem infinitas possibilidades de implementao.
25

USANDO TYPES PARA DINAMIZAR NOSSO JOGO Fizemos algumas adaptaes no nosso jogo do F15, tirando os comandos de linhas simples e implementando os nossos protagonistas por meio de types. A princpio isso trouxe uma pequena reduo de cdigo, afinal o jogo ainda no muito complexo, mas a medida que um programa como esse vai crescendo, fica muito difcil implementar o mesmo sem o uso types, pois teramos que criar milhares de linhas para fazer coisas bem simples. Exemplo 7
Graphics 800, 600 SetBuffer BackBuffer() Type Tnave Field img Field px Field py End Type Global Nave.Tnave = New Tnave Nave\img = LoadImage("midia/f15.bmp") Nave\px = 380 Nave\py = 450 Type Tmeteoro Field img Field px Field py End Type Meteoro.Tmeteoro = New Tmeteoro Meteoro\img = LoadImage("midia/pedra1.png") Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) Meteoro.Tmeteoro = New Tmeteoro Meteoro\img = LoadImage("midia/pedra2.png") Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) Meteoro.Tmeteoro = New Tmeteoro Meteoro\img = LoadImage("midia/pedra3.png") Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) Meteoro.Tmeteoro = New Tmeteoro Meteoro\img = LoadImage("midia/pedra1.png") Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) Meteoro.Tmeteoro = New Tmeteoro Meteoro\img = LoadImage("midia/pedra2.png") Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) Global PONTOS = 0

While Not KeyHit(1) Controle() Fisica() If Colide() Then GameOver() Logica() Draw() Wend End Function Controle() If KeyDown(203) nave\px = nave\px - 1 If KeyDown(205) nave\px = nave\px + 1 End Function Function Logica() Pontos = Pontos + 1 End Function Function Fisica() For This.Tmeteoro = Each Tmeteoro This\py = This\py + 3 If This\py > 600 This\px = Rnd(0,700) This\py = -Rnd(100,500) End If Next End Function Function Draw() DrawImage Nave\img, Nave\px, Nave\py For This.Tmeteoro = Each Tmeteoro DrawImage This\img, This\px, This\py Next Color 255,0,0 Text 10, 10, "PONTOS: " + PONTOS Flip Cls End Function Function Colide() For This.Tmeteoro = Each Tmeteoro If ImagesCollide(nave\img,nave\px,nave\py,0 ,This\img,This\px,This\py,0) Then Return 1 Next End Function Function GameOver() Cls Text 350, 290, "GAME OVER" Text 310, 310, "Voc fez " + PONTOS + " Pontos" Flip Delay(3000) End End Function

Criamos dois types, um para controlar a nave e outro para os meteoros.


Type Tnave Field img Field px Field py End Type Type Tmeteoro Field img Field px Field py

26

End Type

Eles possuem a mesma estrutura, mas optamos por criar dois types para que eles no sejam objetos da mesma lista, caso contrrio a nave seria includa na lista dos meteoros. Dai teramos que criar um campo para identidade e criar um comando If para identificar a identidade e dar o comportamento correto para cada tipo de entidade. Como voc j percebeu, bem mais simples separar entidades lgicas diferentes em types diferentes. Veja as linhas abaixo
Global Nave.Tnave = New Tnave Meteoro.Tmeteoro = New Tmeteoro

Para ter mais respostas voc precisar pressionar mais vezes. Esse tipo de controle importante para tiros intermitentes. Cada vez que voc pressiona a tecla sai apenas um tiro. Veja o exemplo abaixo, onde cada vez que a tecla 57 (barra de espao) pressionada exibida a mensagem Tiro Disparado na tela. Exemplo 8
While Not KeyHit(1) Text 50,10, "Tecle Espao para testar e Esc para sair" If KeyHit(57) Then Print "Tiro Disparado" Wend End

A nave declarada como global e os meteoros no. Isso se d porque a nave ser acessada diretamente da varivel dentro de funes.
Function Controle() If KeyDown(203) nave\px = nave\px - 1 If KeyDown(205) nave\px = nave\px + 1 End Function

Vamos dar um exemplo um pouco mais sofisticado, onde controlamos as teclas direcionais, as setas do teclado. Para cada tecla diferente pressionada, temos uma resposta diferente. Exemplo 9
Graphics 640, 480 While Not KeyHit(1) Text 200,10, "Esc -> sair, Direcionais > testar" If KeyHit(200) Then Print "Para cima" If KeyHit(208) Then Print "Para baixo" If KeyHit(203) Then Print "Para esquerda" If KeyHit(205) Then Print "Para direita" Wend

Mas os objetos meteoros sero acessados sempre via lista, por meio do loop For-Each e as listas tem escopo global.
For This.Tmeteoro = Each Tmeteoro DrawImage This\img, This\px, This\py Next

Nada impede que a nave seja acessada por um lao For-Each, mas lgico que estaramos usando um esforo desnecessrio, afinal esse tipo possui apenas um objeto. INTERAGINDO COM O JOGADOR Nesse momento vamos fazer um estudo especfico sobre os mecanismos de interao entre o jogo e o jogador. Como voc sabe, um jogo no realmente um jogo se no existir a participao de uma pessoa fazendo escolhas, interagindo com o aplicao. Existem trs formas principais de um jogador interagir com um jogo: pelo teclado, pelo mouse e por meio de joysticks. Quando uma tecla for pressionada Por meio do comando KeyHit fazemos a verificao se uma tecla foi pressionada. Perceba o verbo, esse comando verifica se foi pressionada e no se est pressionada. Isso , ele s d uma resposta por cada vez que pressionamos uma tecla.
27

Antigamente, quando eu ainda estava iniciando na programao (isso realmente faz bastante tempo!) os computadores pessoais no tinham um grande poder de processamento e era algo muito comum programadores fazerem jogos com elementos grficos primitivos como caracteres ASCII. O exemplo abaixo cria uma nave a partir de elementos de textos e usa a tecla barra de espao para disparar um mssil. Embora esse tipo de jogo seja pobre graficamente, muito rico em criatividade e vai lhe mostra como se usa o KeyHit para disparar um tiro. Exemplo 10
Graphics 640, 480 SetBuffer BackBuffer() y = 454 chave = 0

While Not KeyHit(1) Text 10,10, "Tecle Esc para sair e Barra de espao para disparar" Text 320, y, "^" Text 320, y+2, "|" Text 312, 458, "X X" ; disparo If KeyHit(57) chave = 1 y = 454 EndIf If chave = 1 Then y = y - 2 Flip Cls Wend

Divertido isso no ? O que espero desse exemplo que voc entenda como funciona ao comando KeyHit e esse exemplo apenas uma ilustrao de um dos usos que podemos fazer dele. Se uma tecla est pressionada Ao contrrio do KeyHit o comando KeyDown verifica se uma tecla est pressionada e retorna verdadeiro caso esteja. Assim, enquanto a tecla estiver pressionada ele causa ao. Esse comando prprio para eventos contnuos como caminhar ou correr, onde ficar apertando a tecla para cada passo incoerente. Assim, com o uso de KeyDown, enquanto a tecla estiver pressionada o personagem caminha. No exemplo abaixo perceba que basta manter a tecla pressionada para que a mensagem seja exibida de forma ininterrupta. Exemplo 11
Print "Esc -> Sair; Space -> Teste" While Not KeyHit(1) If KeyDown(57) Print "esta pressionada!" Print "------------------" EndIf Wend End

Text 10,10, "Tecle Esc para sair, Space para disparar, setas para mover" Text x, y, "^" Text x, y+2, "|" Text x-8, 458, "X X" ; disparo If KeyHit(57) chave = 1 y = 454 EndIf If chave = 1 Then y = y - 2 ;move If KeyDown(203) Then x = x - 1 If KeyDown(205) Then x = x + 1 Flip Cls Wend

Como descobrir os nmeros das teclas Os nmeros das teclas do Blitz3D no tm nenhuma relao com a tabela de caracteres ASCII. Mas no se preocupe, pois ele tem uma ferramenta interna para fornecer o numero de cada tecla. Clique com o mouse na imagem da casinha.

Clique agora em Command Reference.

O passo agora escolher Scancodes Picker

Pronto! Aparece o teclado abaixo.

No prximo exemplo, adaptamos o cdigo na nave de textos para que ela possa se locomover lateralmente por meio do uso das setas direcionais esquerda e direita. Exemplo 12
Graphics 640, 480 SetBuffer BackBuffer() y = 454 x = 320 chave = 0 While Not KeyHit(1)

Aperte com o mouse em uma tecla e veja em cima qual o nmero dela. Inputs de mouse Antes de entrarmos em entradas de dados pelo mouse interessante que aprendamos um output dele, isso , uma sada. Provavelmente e seu jogo voc ir criar
28

botes e talvez menus. Para usar esses recursos fundamental saber onde est posicionado o mouse. Podemos obter esses dados da posio x e y do mouse por meio dos comandos MouseX() e MouseY(). O ponteiro do mouse s vai aparecer em modo de janela. Portanto se o seu jogo vai rodar em FullScreen voc vai ter que providenciar um ponteiro por meio de uma imagem ou por meio de um caractere. No exemplo abaixo usamos o caractere +. Exemplo 13
While Not KeyHit(1) x = MouseX() y = MouseY() Text 10, 10, "Posio X: " + x Text 10, 20, "Posio y: " + y Text x, y, "+" Flip Cls Wend

Exemplo 15
Graphics 800,600,32,1 nave = LoadImage("midia\f15.bmp") While Not KeyHit(1) x = MouseX() y = MouseY() DrawImage nave, x, y Flip Cls Wend

Nesse exemplo provavelmente o mouse aparece, pois est em modo de janela. No exemplo abaixo vamos rodar em modo Fullscreen. Se o Debug estiver ligado, desabilite o mesmo pois ele fora o programa a ser executado em modo de janela. Exemplo 14
Graphics 800, 600 While Not KeyHit(1) x = MouseX() y = MouseY() Text 10, 10, "Posio X: " + x Text 10, 20, "Posio y: " + y Text x, y, "+" Flip Cls Wend

Se um boto do mouse foi pressionado Podemos capturar o pressionar de um boto do mouse por meio do comando MouseHit. Ele retorna verdadeiro apenas uma vez para cada vez que um boto pressionado. Devemos testar qual boto est sendo pressionado por meio de seu nmero. Veja os nmeros de cada boto: 1 boto esquerdo. 2 boto direito. 3 boto do meio. O exemplo abaixo mostra como esse comando utilizado. Exemplo 16
While Not KeyHit(1) If MouseHit(1) Then Print "Boto Esquerdo Pressionado!" If MouseHit(2) Then Print "Boto Direito Pressionado!" If MouseHit(3) Then Print "Boto do Meio Pressionado!" Wend

Usando o mouse para movimentar personagens Podemos usar os dados obtidos do mouse para posicionar um personagem ou ento para o movimentar o mesmo. Em um caso, dizemos que a posio de uma nave, por exemplo, igual posio x e y do mouse; em outro, mais tpicos de rpg, quando o mouse clicado, pegamos a posio atual do ponteiro e fazemos dela a posio de destino do personagem. Como o segundo caso mais complexo, vamos estud-lo em captulos mais avanado. O programa abaixo demonstra uma das formas de usar o mouse para movimentar um personagem.
29

Esse comando tem inmeras utilidades, desde a construo de interface grfica (verificar se um boto foi pressionado), como disparar eventos (abrir uma porta, acionar uma alavanca) ou mesmo disparar tiros intermitentes em um jogo. Se um boto do mouse est pressionado Por meio do comando MouseDown fazemos uma verificao se um boto do mouse est pressionado e ele retornar verdadeiro enquanto este estiver pressionado produzindo ao contnua. Veja o exemplo anterior modificado para esse tipo de evento. Exemplo17
While Not KeyHit(1) If MouseDown(1) Then Print "Boto Esquerdo Pressionado!" If MouseDown(2) Then Print "Boto Direito Pressionado!" If MouseDown(3) Then Print "Boto do Meio Pressionado!" Print ----------------------------- Wend

Usando mouse para interagir com botes O exemplo abaixo mostra como usar os comandos mousex, mousey e mousehit para construir um sistema de botes que provavelmente voc vai usar em seus jogos. Exemplo 18
Graphics 800, 600 ligado = -1 While Not KeyHit(1) x = MouseX() y = MouseY() K = MouseHit(1) Color 180,180,180 Rect 350,400, 100, 40,1 If (x > 350) And (x < 450) If (y > 400) And (y < 440) Color 120,120,120 Rect 350,400, 100, 40,1 If K Then ligado = ligado * (-1) EndIf EndIf Color 0,255,0 If ligado = 1 Then Text 270, 200, "Boto ativado, aperte denovo!" Text x-5, y-5, "+" Flip Cls Wend

Por isso verificamos se a varivel X que contm a posio x atual do mouse est dentro desse limite, isso , se ele maior que 350 e menor que 450.
If (y > 400) And (y < 440)

Se a posio x do mouse est enquadrada dentro do boto, passamos a verificar a posio y do mesmo, pois para a seta do mouse estar localizada dentro, ambos x e y devem estar dentro desses limites. Como o boto desenhado na posio 400 e tem 40 de altura, ento ele ter que estar entre 400 e 440, isso , deve ser maior que 400 e menor que 440.
Color 120,120,120 Rect 350,400, 100, 40,1

Se as variveis de localizao do ponteiro do mouse passaram no dois testes ento desenhamos um novo retngulo sobre o anterior, mas com cor mais escura para indicar que ele est em foco.
If K Then ligado = ligado * (-1)

Explicando...
ligado = -1

Criamos uma chave para indicar se o boto est ligado ou desligado. Deixamos seu estado inicial como -1 ou desligado.
x = MouseX() y = MouseY()

Aqui estamos pegando a posio atual do mouse e guardando suas coordenadas nas variveis x e y.
K = MouseHit(1)

Ainda dentro da verificao, agora hora de saber se o boto esquerdo do mouse foi pressionado. As condies so: se a coordenada x do mouse estiver dentro do boto, e se a coordenada y do mouse estiver dentro do boto e se o boto esquerdo do mouse for pressionado (If K), ento inverta a chave. Isso mesmo, inverta, pois a multiplicao de um nmero por (-1) da o seu valor inverso. Se era -1 vai se tornar 1 e se 1 vira -1.
Color 0,255,0 If ligado = 1 Then Text 270, 200, "Boto ativado, aperte denovo!" Text x-5, y-5, "+"

Nessa linha verificamos se o boto do mouse foi pressionado e guardamos esse resultado na varivel k.
Color 180,180,180

Estamos alterando a cor da paleta de desenho para um cinza claro.


Rect 350, 400, 100, 40, 1

Estamos desenhando um retngulo que ser o nosso boto; isso feito pelo comando Rect. Ele desenhado na posio 350,400 e tem 100 pontos de largura e 40 de altura. Seu tipo de preenchimento 1, isso cheio.
If (x > 350) And (x < 450)

Aqui inicia-se a verificao se o ponteiro do mouse est sobre o boto. O Boto inicia-se em 350 e tem 100 pontos de comprimento.
30

O que fazemos nessa seqncia : primeiro mudamos a cor da paleta para que a mensagem e o cursor do mouse tenham cores diferentes do boto. Depois exibimos a mensagem se o boto estiver ligado. E por ltimo exibimos um cursor para o mouse. Perceba que fizemos um pequeno ajuste para coincidir com o meio do caractere. Em um jogo o ideal que voc faa seus botes a partir de imagens como .bmp ou .jpg. Isso vai deixar seus botes muito mais elegantes e so muito mais leves de processar. A velocidade do mouse

Podemos detectar a velocidade com a qual o mouse se movimenta e usarmos esse dado para dar um controle mais preciso manipulao de nossos personagens e objetos num jogo. Podemos fazer isso por meio do uso dos comandos MousexSpeed e MouseySpeed. Exemplo 19
Graphics 800, 600, 32, 1 While Not KeyHit(1) x = MouseX() y = MouseY() Text x, y, "+" vx = MouseXSpeed() vy = MouseYSpeed() Text 10,10, "Velocidade X: " + vx Text 10,20, "Velocidade Y: " + vy Flip Cls Wend MouseXSpeed se refere a velocidade

Veja que as posies px e py so dadas por um ajuste da posio atual mais a velocidade atual do mouse
px = px + MouseXSpeed() py = py + MouseYSpeed()

Outra coisa que temos que fazer limitar at onde a nave pode ir. Ela no deve atravessar os limites laterais da tela. Fisemos esse controle nas linhas abaixo.
If If If If px px py py > < > < 750 Then px 0 Then px = 550 Then py 0 Then py = = 750 0 = 550 0

que o mouse se locomove na sentido horizontal da tela, isso , direo x. O MouseYSpeed se refere ao movimento vertical. Usando MouseSpeed em jogos Esse comando fantstico para dar uma perfeita movimentao a personagens de jogos e para gerar efeitos de fsica, afinal ele captura com que velocidade o jogador manipula o mouse. Isso pode ser usando tanto para velocidade de um personagem quanto para indicar a fora com a qual se desfere um golpe. No exemplo abaixo usamos o MouseSpeed para mover a nave. Exemplo 20
Graphics 800,600,32,1 nave = LoadImage("midia\f15.bmp") px = 370 py = 400 MoveMouse 400,300 While Not KeyHit(1) px = px + MouseXSpeed() py = py + MouseYSpeed() If px > 750 Then px = 750 If px < 0 Then px = 0 If py > 550 Then py = 550 If py < 0 Then py = 0 DrawImage nave, px, py Flip Cls Wend

Atualizando o Jogo F15 para ser controlado por mouse Estamos fazendo algumas atualizaes no nosso jogo. Agora a nave ser controlado por mouse. Com essa atualizao o controle de nosso avio vai ficar bem mais dinmico e a quantidade de meteoros se tornar muito pouco, deixando o jogo muito fcil. Para superar esse problema, vamos cria um "motor" de criao e de destruio automtica de pedras . Para isso usaremos os Types, pois essa estrutura a nica que permite fazer alocao dinmica de memria, isso , podemos criar de destruir entidade na quantidade que desejarmos, e em tempo de execuo do jogo. Assim, nosso motor criar entidades de forma aleatria e as destruir quando no mais as usar, isso , quando sarem da rea visvel da tela.

Na linha abaixo colocamos o ponteiro do mouse no centro da tela para permitir um melhor controle do mesmo.
MoveMouse 400,300

Exemplo 21
Graphics 800, 600 SetBuffer BackBuffer() Type Tnave

31

Field img Field px Field py End Type Type Tmeteoro Field img Field px Field py End Type Global Nave.Tnave = New Tnave Nave\img = LoadImage("midia/f15.bmp") Nave\px = 380 Nave\py = 450 Global img1 = LoadImage("midia/pedra1.png") Global img2 = LoadImage("midia/pedra2.png") Global img3 = LoadImage("midia/pedra3.png") Global PONTOS = 0 MoveMouse 400,300 While Not KeyHit(1) CriarPedras() Controle() Fisica() If Colide() Then GameOver() Logica() Draw() Wend End Function CriarPedras() sorte = Rnd(0,20) If sorte = 1 Meteoro.Tmeteoro = New Tmeteoro Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) IMG = Rnd(1,3) If IMG = 1 Then Meteoro\img = img1 If IMG = 2 Then Meteoro\img = img2 If IMG = 3 Then Meteoro\img = img3 EndIf End Function Function Controle() Nave\px = Nave\px + MouseXSpeed() End Function Function Logica() Pontos = Pontos + 1 End Function Function Fisica() For This.Tmeteoro = Each Tmeteoro This\py = This\py + 3 If This\py > 600 Delete This End If Next End Function Function Draw() DrawImage Nave\img, Nave\px, Nave\py For This.Tmeteoro = Each Tmeteoro DrawImage This\img, This\px, This\py Next Color 255,0,0

Text 10, 10, "PONTOS: " + PONTOS Flip Cls End Function Function Colide() For This.Tmeteoro = Each Tmeteoro If ImagesCollide(nave\img,nave\px,nave\py,0 ,This\img,This\px,This\py,0) Then Return 1 Next End Function Function GameOver() Cls Text 350, 290, "GAME OVER" Text 310, 310, "Voc fez " + PONTOS + " Pontos" Flip Delay(3000) End End Function

A primeira mudana que fizemos foi no conceito de como usar as imagens dos meteoros. Os nossos meteoros agora sero instanciados dinamicamente em tempo de jogo, isso , no sero carregados como antes, no inicio do jogo, mas sero criados enquanto o jogo estiver em andamento. Por isso no mais uma boa idia carregar as imagens direto do arquivo para o type do meteoro. Decidimos esto carregar as imagens em variveis globais e no objeto meteoro deixaremos apenas uma referncia, isso , o campo do meteoro vai apontar para uma dessas trs variveis e no mais conter as imagens. Assim, carregaremos apenas 3 imagens e nosso jogo vai fluir de maneira mais suave, sem lags.
Global img1 = LoadImage("midia/pedra1.png") Global img2 = LoadImage("midia/pedra2.png") Global img3 = LoadImage("midia/pedra3.png")

Como nosso jogo agora ser controlado por mouse, colocamos o mouse no centro da tela.
MoveMouse 400,300

Nosso loop do jogo recebeu uma nova funo, a funo CriarPedras().


While Not KeyHit(1) CriarPedras() Controle() Fisica() If Colide() Then GameOver() Logica() Draw()

32

Wend

A principal alterao no nosso jogo se deu na criao de nosso motor construtor de meteoros. Veja o cdigo abaixo.
Function CriarPedras() sorte = Rnd(0,20) If sorte = 1 Meteoro.Tmeteoro = New Tmeteoro Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) IMG = Rnd(1,3) If IMG = 1 Then Meteoro\img = img1 If IMG = 2 Then Meteoro\img = img2 If IMG = 3 Then Meteoro\img = img3 EndIf End Function

Como voc j percebeu, a funo invocada a cada iterao, isso , mais ou menos 60 vezes por segundo. Para que no sejam criados milhares de meteoros, condicionamos a sua criao a um sorteio sorte = Rnd(0,20). Caso seja sorteado o nmero 1, ai ser criado um novo meteoro. A posio x do meteoro sorteada Meteoro\px = Rnd(0,700) assim como tambm a sua posio y Meteoro\py = -Rnd(100,700). A imagem do meteoro tambm dada por sorteio IMG = Rnd(1,3). Dai fazemos uma referncia a uma das trs variveis globais que possuem imagem Meteoro\img = img1. Como agora controlamos a nave pelo mouse, a funo Controle(), sofreu alteraes.
Function Controle() Nave\px = Nave\px + MouseXSpeed() End Function

Com esse algoritmo voc pode criar jogos infinitos, com inteligncia artificial extremamente complexa, com pouco esforo de trabalho e com tima economia de processamento. Como voc ver a frente, esse recurso tambm o ideal para disparar tiros. Os tiros sero criados e destrudos com pouqussimo esforo e em poucas linhas. Inputs de Joysticks O Blitz3D tambm oferece uma srie de recursos de suporte a joysticks, os controles tpicos de videogames. Esses recursos so muito importantes, pois alguns jogos que necessitam de maior controle so mais agradveis de serem jogados com joysticks. Estou fazendo esses exemplos para um joystick de oito botes. Mas no se preocupe, pois isso se adapta a qualquer tipo de modelo. Se um boto foi pressionado Por meio do comando JoyHit podemos fazer uma varedura no joystick para verificamos se um boto foi pressionado. Esse comando s d um retorno por cada vez que o boto for pressionado. o comando tpico de controle de tiros intermitentes. Exemplo 22
While Not KeyHit(1) If JoyHit(1) Print "boto If JoyHit(2) Print "boto If JoyHit(3) Print "boto If JoyHit(4) Print "boto If JoyHit(5) Print "boto If JoyHit(6) Print "boto If JoyHit(7) Print "boto If JoyHit(8) Print "boto Wend 1 2 3 4 5 6 7 8 pressionado" pressionado" pressionado" pressionado" pressionado" pressionado" pressionado" pressionado"

A ultima alterao foi na nossa funo de fsica, que foi usada para destruir meteoros.
Function Fisica() For This.Tmeteoro = Each Tmeteoro This\py = This\py + 3 If This\py > 600 Delete This End If Next End Function

Quando um meteoro passa o limite da tela If This\py > 600 ele destrudo com o comando Delete: Delete This. Parabns!!!! Voc acaba de entender um dos mais fantsticos conceitos de desenvolvimento de jogos: motores de criao e destruio dinmica de entidades. Sem essa estratgia impossvel criar jogos complexos e seria muito difcil gerenciar qualquer tipo de jogo.
33

Se um boto est pressionado Por meio do comando JoyDown fazemos uma verificao se algum boto do joystick est pressionado, dando retornos contnuos enquanto ele estiver neste estado. Veja o exemplo abaixo. Exemplo 23
While Not KeyHit(1) If JoyDown(1) Print pressionado" If JoyDown(2) Print pressionado" If JoyDown(3) Print pressionado" If JoyDown(4) Print pressionado" "boto 1 "boto 2 "boto 3 "boto 4

If JoyDown(5) pressionado" If JoyDown(6) pressionado" If JoyDown(7) pressionado" If JoyDown(8) pressionado" Wend

Print "boto 5 Print "boto 6 Print "boto 7 Print "boto 8

Wend EndIf Wend

Qual boto foi pressionado? Com o comando GetJoy, em vez de testar um boto especfico, podemos fazer um teste genrico onde ele retorna o nmero do boto pressionado. Ele muito importante para dar a opo de o jogador escolher qual boto ir usar para qual ao. O exemplo abaixo d uma idia de como fazer isso. No se assuste com o tamanho, pois a nica coisa nova ai o GetJoy(). Exemplo 24
Graphics 800, 600 btn_tiro = 1 btn_bomba = 2 tiro = 1 bomba = 2 While Not KeyHit(1) If JoyHit(btn_tiro) Print "Tiro" + tiro + " disparado" tiro = tiro + 1 EndIf If JoyHit(btn_bomba) Print "Bomba" + bomba + " disparada" bomba = bomba + 1 EndIf Text 250, 10, "pressione space para configurar" Text 250, 30, "Tiro BTN: " + btn_tiro Text 250, 45, "Bomba BTN: " + btn_bomba If KeyHit(57) chave = 0 While (chave = 0) Text 250, 10, "Pressione um boto para o tiro e Space para sair" Text 250, 30, "Tiro BTN: " + btn_tiro a = GetJoy() If a > 0 Then btn_tiro = a If KeyHit(57) Then chave = 1 Flip Cls Wend chave = 0 While (chave = 0) Text 250, 10, "Pressione um boto para Bomba e Space para sair" Text 250, 30, "Bomba BTN: " + btn_bomba a = GetJoy() If a > 0 Then btn_bomba = a If KeyHit(57) Then chave = 1 Flip Cls

Movendo Com joystick Os comandos JoyX() e JoyY() so responsveis pelo controle dos eixos direcionais do joystic. Eles retornam os valores "1" e " -1" quando esses eixos so acionados, assim indicam se a posio x e y devem ser incrementadas ou diminudas. O programa abaixo controla o helicptero por meio do jopystic.

Exemplo 25
Graphics 800, 600 px = 400 py = 300 nave = LoadImage("midia\heli.bmp") While Not KeyHit(1) Cls JX = JoyX() * 2 JY = JoyY() * 2 Px = Px + JX Py = Py + Jy DrawImage nave, Px, Py Flip Wend

Como esse comando retorna 1 ou -1, estamos multiplicando o mesmo por 2 para que o helicptero possa se mover mais rpido.
JX = JoyX() * 2 JY = JoyY() * 2

Persistncia At agora s aprendemos a colocar dados na memria latente, isso , na memria ram. Quando criamos uma varivel ou um type estamos fazendo uma reserva de uma parte da memria ram para guardar nossos dados. Mas esse tipo de dados so muito volteis, pois funcionam por meio de dispositivos eltricos que simulam estruturas lgicas.
34

Quando o programa encerrado ou o computador desligado esse tipo de dado se perde. Em jogos existem certos tipos de dados que no podem ser perdidos; entre eles esto os placares de melhores partidas ou os arquivos de jogos salvos. Para que possamos recuperar esse tipo de dados temos que usar outra tcnica: a persistncia. Para gerar dados persistentes devemos colocar esses dados em dispositivos eltricomagnticos, como disquetes, discos rgidos e fitas de dados ou em outros tipos de dispositivos que possam por algum meio fsico ou qumico conservar o estado de dados, mesmo sem o fornecimento constante de energia. O Blitz3D pode gerar arquivos de texto ou binrios para criar dados persistentes. Nosso estudo de como o Blitz faz isso vai ser bem objetivo para nos capacitar a criar persistncia para ndices de escores, arquivos de dados e salvar estados de jogos. Portanto, no iremos abordar todos os recursos que essa ferramenta possui para lidar com dados, pois isso levaria pelo menos uma centena de pginas. Manipulando Strings Por meio dos comandos de manipulao de arquivos podemos gravar uma ou mais variveis de strings em um arquivo de dados. O exemplo abaixo grava uma string em um arquivo. Exemplo 26
arquivo_aberto = WriteFile("meuarquivo.ovo") WriteString(arquivo_aberto, "meu primeiro dado") CloseFile(arquivo_aberto) Print "Gravando..." WaitKey

Quando usamos o comando WriteFile ele procura pelo arquivo indicado. Se no encontrar ele cria um novo arquivo. Caso encontre um arquivo ele o abre para gravao, portanto todo seu contedo sobrescrito. Se no gravarmos nada, ele fica em branco. O nome do arquivo "meuarquivo.ovo" de nossa escolha e podemos dar a extenso que quisermos. Nesse exemplo no colocamos endereamento do arquivo, isso , no dissemos em que pasta ele est, assim o Blitz3D compreende que o arquivo est, ou deve ser criado no mesmo local que est gravado o cdigo fonte do programa, isso , na sua pasta de projetos. Portanto se voc criou um arquivo de cdigo novo e ainda no o salvou, isso pode dar problema, pois ele vai entender que o diretrio de projeto o diretrio raiz do Blitz3D, onde esto os arquivos desse programa. Podemos gerenciar onde um arquivo ser salvo ou de onde ser lido por meio das resolues de endereo absoluto ou relativo, por exemplo dados\meuarquivo.ovo ou C:\projetodoovo\dados\meuarquivo.ovo. Esses comandos no criam diretrios. Se os diretrios no existem o arquivo no ser salvo. Perceba que quando abrimos o arquivo criamos uma varivel e atribumos o resultado da abertura a ela arquivo_aberto = isso se d porque no manipulamos o arquivo por meio de seu nome no disco rgido, mas por meio de uma referncia que o Blitz3D cria para ele. Perceba que a partir de agora iremos controlar esse arquivo aberto por meio dessa varivel criada para ele.
WriteString(arquivo_aberto, "meu primeiro dado")

Vamos explicao...
arquivo_aberto = WriteFile("meuarquivo.ovo")

O que essa linha faz abrir um arquivo para gravar dados nele. O comando usado para abrir um arquivo para gravao WriteFile( ). S podemos escrever dados em um arquivo se ele for aberto com o mtodo de gravao. Existem mtodos de abertura de arquivos apenas para leitura, veremos isso depois.
35

nessa linha que estamos gravando os dados de texto no arquivo. O comando WriteString() grava uma string em um arquivo. Sua forma de uso WriteString(arquivo,string). Veja que o primeiro argumento a varivel criada na abertura do arquivo arquivo_aberto ela indica onde vamos gravar a string. O segundo argumento deve ser uma string ou uma varivel de string; nesse caso usamos

uma string literal, isso , um texto meu primeiro dado.


CloseFile(arquivo_aberto)

Agora que j gravamos os dados no arquivo nos resta fechar esse arquivo e isso que o comando CloseFile faz. Como voc poder ver mais adiante, no importa com qual comando voc abre um arquivo, todos sero fechados por CloseFile.
Print "Gravando..."

Veja que usamos o mtodo ReadString() para pegar a string do arquivo representado por arquivo_aberto. Colocamos essa string dentro de uma varivel de strings texto$ para no perdermos o seu contedo.
CloseFile(arquivo_aberto)

Fechamos o arquivo
Print "Contedo do arquivo: " + texto$

Essa linha no possui funo tcnica, colocamos ai apenas para informar que a operao foi concluda. Gravando vrias strings Para gravar vrias strings basta colocar vrios comandos WriteString(). Veja o exemplo abaixo. Exemplo 27
arquivo_aberto = WriteFile("meuarquivo.ovo") WriteString(arquivo_aberto, "meu primeiro dado") WriteString(arquivo_aberto, "meu segundo dado") WriteString(arquivo_aberto, "meu terceiro dado") CloseFile(arquivo_aberto) Print "Gravando..." WaitKey

Aqui imprimimos a string lida do arquivo. Lendo vrias strings Assim como para escrever vrias strings devemos usar vrios WriteString, para ler vrias strings deveremos usar vrias vezes ReadString. Exemplo 29
arquivo_aberto = ReadFile("meuarquivo.ovo") texto$ = ReadString(arquivo_aberto) Print "Contedo do arquivo: " + texto$ texto$ = ReadString(arquivo_aberto) Print "Contedo do arquivo: " + texto$ texto$ = ReadString(arquivo_aberto) Print "Contedo do arquivo: " + texto$ CloseFile(arquivo_aberto) WaitKey

Simples no ? Como ler strings de arquivos Para ler uma string de um arquivo devemos primeiro abrir o arquivo para leitura, isso pode ser feito com o comando ReadFile() e devemos ler string por string por meio do comando ReadString(). Veja o exemplo abaixo onde vamos ler o contedo do arquivo criado no programa anterior. Exemplo 28
arquivo_aberto = ReadFile("meuarquivo.ovo") texto$ = ReadString(arquivo_aberto) CloseFile(arquivo_aberto) Print "Contedo do arquivo: " + texto$ WaitKey

Manipulando Inteiros Para manipular dados de inteiros em arquivos podemos proceder da mesma forma que fizemos com as strings, mas trocando os comando de gravao e de leitura para WriteInt() e ReadInt(). O exemplo abaixo grava 3 inteiros em um arquivo. Exemplo 30
arquivo_aberto = WriteFile("meuarquivo.dovo") WriteInt(arquivo_aberto, 11111) WriteInt(arquivo_aberto, 22222) WriteInt(arquivo_aberto, 33333) CloseFile(arquivo_aberto) Print "Dados gravados..." WaitKey

Esses dados de inteiros podem ser acessados por meio de ReadInt(), veja no exemplo. Exemplo 31
arquivo_aberto = ReadFile("meuarquivo.dovo") For x = 0 To 2 dado = ReadInt(arquivo_aberto) Print "Numero lido: " + dado Next CloseFile(arquivo_aberto) Print "Dados gravados..." WaitKey

Explicando...
arquivo_aberto = ReadFile("meuarquivo.ovo")

Aqui usamos o mtodo de abertura para leitura que no altera o contedo do arquivo. Perceba que colocamos a referncia do arquivo em uma varivel.
texto$ = ReadString(arquivo_aberto)

36

Veja que nesse exemplo, ai invs de ficar repetindo trs vezes os comando ReadInt() e Print, colocamos os mesmos dentro de um lao com trs iteraes. Criando um sistema de escores Vamos criar agora um exemplo de como fazer um mdulo de melhores pontuaes. Nesse exemplo vamos faz-lo para apenas 5 jogadores para que no fique muito grande, mas muito fcil modific-lo para a quantidade que voc quiser. Esse exemplo ser criado com arquitetura genrica, assim poder ser reutilizado em qualquer projeto. Nessa primeira verso o fizemos com um estilo mais repetitivo, sem colees para que o mecanismo de funcionamento seja mais fcil de ser compreendido. Exemplo 32
Graphics 800, 600 Global nome1$ Global ponto1 Global nome2$ Global ponto2 Global nome3$ Global ponto3 Global nome4$ Global ponto4 Global nome5$ Global ponto5 If FileType("ovoscores.scr") Then LerScores() While Not KeyHit(1) Text 200, 20, "------------- SORTEIO DE 0 A 1000 -------------" Text 250, 50, "Para jogar Aperte Barra de Espao" Text 200, 450, "------------------SCORES --------------------" Text 200, 470, "1." + nome1$ + " " + ponto1 Text 200, 485, "2." + nome2$ + " " + ponto2 Text 200, 500, "3." + nome3$ + " " + ponto3 Text 200, 515, "4." + nome4$ + " " + ponto4 Text 200, 530, "5." + nome5$ + " " + ponto5 Text 200, 555, "----------------------------------------------" If KeyHit(57) seuponto = Rnd(1000) Text 200, 200, "Voc fez " + seuponto + " pontos" If seuponto > ponto5

Text 200, 250, "Voc est entre as melhores pontuaes!" Locate 200, 300 seunome$ = Input$("Digite seu nome: ") GravarScores(seunome$, seuponto) LerScores() Else Text 200, 250, "Aperte space para continuar..." While Not KeyHit(57) Wend EndIf EndIf Flip Cls Wend ;*********************** METODO DE LEITURA DE DADOS ************************* Function LerScores() aberto = ReadFile ("ovoscores.scr") nome1$ = ReadString(aberto) ponto1 = ReadInt(aberto) nome2$ = ReadString(aberto) ponto2 = ReadInt(aberto) nome3$ = ReadString(aberto) ponto3 = ReadInt(aberto) nome4$ = ReadString(aberto) ponto4 = ReadInt(aberto) nome5$ = ReadString(aberto) ponto5 = ReadInt(aberto) CloseFile(aberto) End Function ;******************** METODO DE ADIO DE DADOS ********************** Function GravarScores(jogador$, pontos) ;pegando os dados atuais do arquivo If FileType("ovoscores.scr") aberto = ReadFile ("ovoscores.scr") play1$ = ReadString(aberto) score1 = ReadInt(aberto) play2$ = ReadString(aberto) score2 = ReadInt(aberto) play3$ = ReadString(aberto) score3 = ReadInt(aberto) play4$ = ReadString(aberto) score4 = ReadInt(aberto) play5$ = ReadString(aberto) score5 = ReadInt(aberto) CloseFile(aberto) EndIf ; fasendo seleo de dados If pontos > score5 score5 = pontos play5$ = jogador$ EndIf If pontos > score4 score5 = score4 play5$ = play4$ score4 = pontos play4$ = jogador$ EndIf

37

If pontos > score3 score4 = score3 play4$ = play3$ score3 = pontos play3$ = jogador$ EndIf If pontos > score2 score3 = score2 play3$ = play2$ score2 = pontos play2$ = jogador$ EndIf If pontos > score1 score2 = score1 play2$ = play1$ score1 = pontos play1$ = jogador$ EndIf ; gravar dodos depois da seleo aberto = WriteFile("ovoscores.scr") WriteString(aberto, play1$) WriteInt(aberto, score1) WriteString(aberto, play2$) WriteInt(aberto, score2) WriteString(aberto, play3$) WriteInt(aberto, score3) WriteString(aberto, play4$) WriteInt(aberto, score4) WriteString(aberto, play5$) WriteInt(aberto, score5) CloseFile(aberto) End Function

Text 250, 50, "Para jogar Aperte Barra de Espao" Text 200, 450, "------------------SCORES --------------------" Text 200, 470, "1." + nome1$ + " " + ponto1 Text 200, 485, "2." + nome2$ + " " + ponto2 Text 200, 500, "3." + nome3$ + " " + ponto3 Text 200, 515, "4." + nome4$ + " " + ponto4 Text 200, 530, "5." + nome5$ + " " + ponto5 Text 200, 555, "----------------------------------------------"

Nesse trecho no h segredos. Estamos iniciando o loop do jogo e exibindo informaes na tela.
If KeyHit(57) seuponto = Rnd(1000) Text 200, 200, "Voc fez " + seuponto + " pontos"

Tudo comea com o apertar da tecla 57, a barra de espaos. Ai usamos o gerador de nmeros aleatrios Rnd() para fazer o sorteio de pontos de 0 a 1000. Depois informamos qual foi pontuao alcanada.
If seuponto > ponto5 Text 200, 250, "Voc est entre as melhores pontuaes!" Locate 200, 300 seunome$ = Input$("Digite seu nome: ") GravarScores(seunome$, seuponto) LerScores()

Explicando tudinho...
Global Global Global Global Global Global Global Global Global Global nome1$ ponto1 nome2$ ponto2 nome3$ ponto3 nome4$ ponto4 nome5$ ponto5

Nessas linhas ai declaramos 5 variveis globais para conter os nomes de melhores jogadores e 5 variveis para conter suas pontuaes.
If FileType("ovoscores.scr") Then LerScores()

Essa linha muito importante, pois no podemos ler um arquivo que no existe, pois do contrrio dar erro. O comando FileType retorna 0 se o arquivo no existe, retorna 1 se ele existe e 2 se for um diretrio. Assim, essa primeira leitura ai s vai ser feita se o arquivo j foi criado.
While Not KeyHit(1) Text 200, 20, "------------- SORTEIO DE 0 A 1000 -------------"

Se a pontuao maior que a menor pontuao dos melhores escores significa que voc vai entrar para o Hall da fama... Ento a primeira coisa a fazer dizer que voc est dentro. O que fazemos depois pegar o nome do sortudo por meio do comando Input. Perceba que usamos o comando Locate para dizer onde queremos que o input aparea. Depois de obter o nome, passamos o nome e a pontuao para a funo de gravao de scores GravarScores(seunome$, seuponto) . O ultimo passo atualizar o nosso escore exibido na tela. Para isso chamamos a funo LerScores().
Else Text 200, 250, "Aperte space para continuar..." While Not KeyHit(57) Wend EndIf

38

Esse trecho ai de cdigo s executa se sua pontuao no estiver entre as melhores. O que ele faz simplesmente criar um mecanismo de retardo para dar tempo de ver a pontuao mesmo que ela no seja boa. Para passar por isso basta pressionar a barra de espaos.
EndIf Flip Cls Wend

existe, no poderemos e nem precisaremos fazer isso. Por isso nessa linha acima testamos para ver se ele existe, caso contrrio poderia ocorrer um erro.
play1$ score1 play2$ score2 play3$ score3 play4$ score4 play5$ score5 = = = = = = = = = = ReadString(aberto) ReadInt(aberto) ReadString(aberto) ReadInt(aberto) ReadString(aberto) ReadInt(aberto) ReadString(aberto) ReadInt(aberto) ReadString(aberto) ReadInt(aberto)

Bom, isso foi o fim do nosso cdigo principal. Faltam agora as funes.
Function LerScores() aberto = ReadFile ("ovoscores.scr") nome1$ = ReadString(aberto) ponto1 = ReadInt(aberto) nome2$ = ReadString(aberto) ponto2 = ReadInt(aberto) nome3$ = ReadString(aberto) ponto3 = ReadInt(aberto) nome4$ = ReadString(aberto) ponto4 = ReadInt(aberto) nome5$ = ReadString(aberto) ponto5 = ReadInt(aberto) CloseFile(aberto) End Function

Veja que usamos variveis locais para conter temporariamente os dados lidos do arquivo. Fizemos isso para no poluir os dados globais de escores. Essas variveis sero destrudas quanto a funo chegar em EndFunction.
; fazendo seleo de dados If pontos > score5 score5 = pontos play5$ = jogador$ EndIf

Essa funo de leitura muito simples. A nica coisa que voc deve ficar atento aqui que, em primeiro lugar, montamos uma estrutura do tipo ler uma string e ler um int; ento essa estrutura deve ser repetida na funo de gravao de dados, isso , gravar uma string, gravar um int... Se as duas funes no tiverem a mesma estrutura vai ocorrer um erro lgico. Perceba tambm que estamos carregando os dados diretamente para as variveis globais definidas para manipular os escores do jogo. Isso significa que se voc quiser usar essas funes em um projeto seu, tambm ter que declarar aquelas variveis globais l.
Function GravarScores(jogador$, pontos)

Aqui comeamos a fazer a seleo dos escores. Devemos comparar um por um, a partir do ultimo, para colocar o novo escore no local correto. Perceba que verificamos se a nova marca maior que o ultimo colocado do Ranking If pontos > score5, se essa marca realmente for maior ento gravamos ela da ultima posio score5 = pontos e o passo seguinte colocar o nome do pontuador l tambm play5$ = jogador$. Lembre-se que as variveis pontos e jogador$ so aquelas que recebemos como argumento no cabealho da funo, isso , os dados do ultimo jogador que dever entrar nos melhores escores.
If pontos > score4 score5 = score4 play5$ = play4$ score4 = pontos play4$ = jogador$ EndIf

Perceba que nossa funo de gravar escores aceita dois parmetros. Um deve conter o nome do jogador e o outro a sua pontuao.
;pegando os dados atuais do arquivo If FileType("ovoscores.scr")

Como voc se lembra, o mtodo de abertura de arquivos para gravao WriteFile apaga o contedo de um arquivo antes de gravar algo nele, por isso precisamos colher todos dos dados que existem nele antes de gravar algo. Mas perceba que se esse arquivo no
39

Veja que a partir do penltimo a coisa fica um pouco mais complicada, pois se o novo jogador tiver uma marca maior que a dele, no basta colocar no lugar, o antigo ocupante daquela colocao dever ser rebaixado para a posio de baixo. De novo, a primeira coisa a se saber se a nova pontuao maior que a do quarto

colocado do ranking pontos > score4. Se isso for verdadeiro devemos passar o antigo ocupante para a colocao abaixo, seno os dados dele sero perdidos. Primeiro passamos os pontos score5 = score4 o passo seguinte foi passar o nome dele para baixo play5$ = play4$. Agora sim poderemos colocar o novo jogador na posio 4 do ranking. Primeiro colocamos os pontos score4 = pontos e depois o nome play4$ = jogador$.
If pontos > score3 score4 = score3 play4$ = play3$ score3 = pontos play3$ = jogador$ EndIf If pontos > score2 score3 = score2 play3$ = play2$ score2 = pontos play2$ = jogador$ EndIf If pontos > score1 score2 = score1 play2$ = play1$ score1 = pontos play1$ = jogador$ EndIf

Note com cuidado que a forma de gravar tenha a mesma estrutura da forma de ler o arquivo, isso :
String Int String Int String Int String Int String Int

As linhas acima continuam o processo de colocar o jogador e seus pontos no local correto do ranking e rebaixando os antigos ocupantes. Elas possuem a mesma lgica do processo explicado acima e por isso voc j sabe como funciona.
; gravar dodos depois da seleo aberto = WriteFile("ovoscores.scr") WriteString(aberto, play1$) WriteInt(aberto, score1) WriteString(aberto, play2$) WriteInt(aberto, score2) WriteString(aberto, play3$) WriteInt(aberto, score3) WriteString(aberto, play4$) WriteInt(aberto, score4) WriteString(aberto, play5$) WriteInt(aberto, score5) CloseFile(aberto) End Function

Por fim, no momento final, depois de ter ajustado todos os pontuadores no local correto, basta gravar esses dados ajustados no arquivo de dados e isso voc tambm j sabe como se faz.

Incluso de arquivos Fora raras excees de profunda genialidade, bons jogos so programas bem grandes e, sendo assim, gerenciar um cdigo fonte desses algo bem complexo. A melhor maneira de fazer isso sem se perder no emaranhado das linhas a tcnica de dividir para conquistar isso , saber criar mdulos de cdigo que efetuem tarefas especficas e que sejam separados no s logicamente (funes), mas fisicamente tambm (arquivos). Se nossos jogos tiverem apenas um arquivo e tiver milhares de linhas teremos pelo menos 2 inconvenientes: 1. s uma pessoa pode trabalhar por vez. 2. passaremos muitas horas do projeto navegando e procurando os mdulos dentro do cdigo fonte. Para solucionar isso as linguagens de programao mais recentes permitem quem sejam criados arquivos externos de cdigo fonte que podem ser includos no projeto. As principais vantagens dessa tcnica so. 1. Melhor arquitetura do projeto. 2. Modularizao do software. 3. Maior facilidade para corrigir erros e fazer modificaes 4. Possibilidade de trabalhar em equipes 5. Software desacoplado 6. Reuso de software Perceba que s existem vantagens em se trabalhar assim. Como incluir arquivos Para incluir arquivos devemos primeiro possuir um arquivo principal no projeto, que normalmente ter o nome do jogo ou ento se chamar game.bb, ou principal.bb ou algum outro nome que o identifique como o
40

arquivo principal, e dentro dele darmos o comando de incluso Include arquivo.bb. Lembre-se que o programa s poder ser executado e compilado a partir do arquivo principal seno no funcionar. Exemplo prtico Em nosso exemplo prtico vamos criar um simples jogo de dados com primitivas grficas 2D. Nosso jogo possuir 2 arquivos: o principal que ser o arquivo game.bb e o arquivo auxiliar que ser o arquivo dado.bb. A estrutura de controle do jogo em si ficar no arquivo principal e o arquivo a ser includo ser responsvel por gerenciar o dado. Isso , ele ser construdo segundo o princpio da coeso, pelo qual ele s cuidar de uma coisa especfica: o dado, suas propriedades e seu comportamento. Essa a chave do sucesso... enquanto o arquivo principal cuida da lgica geral do jogo, como um maestro, os arquivos includos so especficos, cada um cuida de um objeto ou um responsabilidade determinada. Mas vamos a parte prtica.

End Function Shows() Text 50,10, "*************************************** ***********************" Text 50,22, "************************* DADOS ****************************" Text 50,34, "*************************************** ***********************" Text 50,450,"**************** PRESSIONE SPACE PARA JOGAR ******************" End Function

Perceba que logo depois de configurar do modo grfico do jogo


Graphics 640, 480 SetBuffer BackBuffer()

Fizemos a incluso do arquivo que contem a estrutura e os mtodos do dado:


Include "Dado.bb"

O arquivo principal sempre ter o loop do jogo, onde tudo acontece:


While Not KeyHit(1)

E tambm conter as funes de controle do jogo dentro desse loop:


Shows() If KeyHit(57) Then Dado_Jogar() Dado_Exibir()

Veja acima que estamos invocado duas funes que foram declaradas no arquivo Dado.bb e uma do prprio arquivo principal. Arquivo Dado.bb
Global Dado_dado = 6 Function Dado_Jogar() Dado_dado = Rnd(1,6) End Function Function Dado_Exibir() Color 100, 100, 100 Rect 216, 136, 208, 208 Color 160, 160, 160 Rect 217, 137, 206, 206 Color 220, 220, 220 Rect 218, 138, 204, 204 Color 255, 255, 240 Rect 220, 140, 200, 200 Color 0,0,200 If Dado_dado = 1 Oval 300, 220, 40, 40 EndIf If Dado_dado = 2 Oval 240, 160, 40, 40 Oval 360, 280, 40, 40 EndIf If Dado_dado = 3 Oval 240, 160, 40, 40 Oval 300, 220, 40, 40 Oval 360, 280, 40, 40 EndIf If Dado_dado = 4

Arquivo Game.bb
Graphics 640, 480 SetBuffer BackBuffer() Include "Dado.bb" While Not KeyHit(1) Shows() If KeyHit(57) Then Dado_Jogar() Dado_Exibir() Flip Cls Wend

41

Oval 240, 160, 40, Oval 360, 160, 40, Oval 240, 280, 40, Oval 360, 280, 40, EndIf If Dado_dado = 5 Oval 240, 160, 40, Oval 360, 160, 40, Oval 300, 220, 40, Oval 240, 280, 40, Oval 360, 280, 40, EndIf If Dado_dado = 6 Oval 240, 160, 40, Oval 240, 220, 40, Oval 240, 280, 40, Oval 360, 160, 40, Oval 360, 220, 40, Oval 360, 280, 40, EndIf Color 255,255,255 End Function

40 40 40 40 40 40 40 40 40 40 40 40 40 40 40

localizar e saber o que cada mtodo faz e para qual objeto ele faz.
Function Dado_Exibir()

Essa funo tem a responsabilidade de exibir o dado sorteado na tela. Embora seja um pouco grande, ela toda trabalha com apenas 3 conceitos: mudar a cor da paleta de desenho por meio do comando Color red, green, blue , desenhar quadrados por meio do comando Rect posio x, posio y, largura, altura e desenhar crculos por meio do comando Oval posio x, posio y, largura, altura.
Color 100, 100, 100 Rect 216, 136, 208, Color 160, 160, 160 Rect 217, 137, 206, Color 220, 220, 220 Rect 218, 138, 204, Color 255, 255, 240 Rect 220, 140, 200, 208 206 204 200

Embora esse arquivo seja um pouco maior at mais simples que o anterior.
Global Dado_dado = 6

Veja que declaramos uma varivel global para dizer qual o valor atual do dado, assim o ultimo dado sorteado sempre aparecer na tela. Embora seja desaconselhvel trabalhar com variveis globais, nesse caso no estamos utilizando essa fora da estrutura desse arquivo, ento isso menos grave, pois no gera dependncias externas. Perceba que adotamos a seguinte nomenclatura para as variveis: arquivo + _ + nome. Isso muito importante por dois motivos: sempre saberemos a localizao fsica de uma varivel e no corremos o risco de redefinir ou alterar uma varivel em outro arquivo.
Function Dado_Jogar() Dado_dado = Rnd(1,6) End Function

Nesse trecho de cdigo desenhamos o dado, os quadrados. Veja que na verdade fizemos quatro quadrados com cores diferentes, de um cinza mais escuro para uma cor mais clara. Fizemos isso para dar uma sensao de profundidade no objeto por meio do efeito de sombra.
If Dado_dado = 1 Oval 300, 220, 40, 40 EndIf

Nessa parte do cdigo estamos verificando qual o valor do dado sorteado e desenhando a quantidade de bolinhas correspondentes nele. Acima vemos o teste para saber se o dado sorteado tem o valor 1. Se isso verdadeiro, desenha apenas uma bolinha no centro da tela. Veja outra parte do cdigo abaixo.
If Dado_dado = Oval 240, 160, Oval 360, 160, Oval 300, 220, Oval 240, 280, Oval 360, 280, EndIf 5 40, 40, 40, 40, 40, 40 40 40 40 40

Nossa primeira funo responsvel por fazer o lanamento do dado. Veja que ela faz isso por meio de um gerador de nmeros aleatrios. O comando Rnd() funciona com a seguinte configurao Rnd(numero inicial, numero final). Assim, determinamos que ele dever fazer sorteios de nmeros que se enquadrem entre 1 at 6. Perceba que tambm usamos o mesmo sistema de nomenclatura arquivo + _ + nome para identificar as funes. Isso nos dar uma enorme garantia de eficincia para
42

Nessa parte o teste para ver se o valor sorteado foi 5 e se assim o for, desenhamos 5 bolinhas no dado.
Color 255,255,255 End Function

Veja que no final do cdigo colocamos a paleta de desenho em sua cor padro, isso ,

branco, seno as mensagens na tela teriam sua cor alterada. Ultimo Upgrade no jogo F15 Como ultima adaptao no nosso jogo, vamos reeditar o arquivo do exemplo 32 e fazer dele um componente de software. Vamos salv-lo como Scores.bb e vamos incluir o mesmo no nosso arquivo do jogo, que vai se chamar agora F15.bb. Vamos primeiro s alteraes do Arquivo principal, que agora se chama "F15.bb" Arquivo "F15.bb"
Graphics 800, 600 SetBuffer BackBuffer() Include "Scores.bb" Type Tnave Field img Field px Field py End Type Global Nave.Tnave = New Tnave Nave\img = LoadImage("midia/f15.bmp") Nave\px = 380 Nave\py = 450 Type Tmeteoro Field img Field px Field py End Type Global img1 = LoadImage("midia/pedra1.png") Global img2 = LoadImage("midia/pedra2.png") Global img3 = LoadImage("midia/pedra3.png") Global PONTOS = 0 MoveMouse 400,300 While Not KeyHit(1) CriarPedras() Controle() Fisica() If Colide() Then GameOver() Logica() Draw() Wend End Function CriarPedras() sorte = Rnd(0,20) If sorte = 1 Meteoro.Tmeteoro = New Tmeteoro Meteoro\px = Rnd(0,700) Meteoro\py = -Rnd(100,700) IMG = Rnd(1,3) If IMG = 1 Then Meteoro\img = img1 If IMG = 2 Then Meteoro\img = img2 If IMG = 3 Then Meteoro\img = img3 EndIf End Function Function Controle()

Nave\px = Nave\px + MouseXSpeed() End Function Function Logica() Pontos = Pontos + 1 End Function Function Fisica() For This.Tmeteoro = Each Tmeteoro This\py = This\py + 3 If This\py > 600 Delete This End If Next End Function Function Draw() DrawImage Nave\img, Nave\px, Nave\py For This.Tmeteoro = Each Tmeteoro DrawImage This\img, This\px, This\py Next Color 255,0,0 Text 10, 10, "PONTOS: " + PONTOS Flip Cls End Function Function Colide() For This.Tmeteoro = Each Tmeteoro If ImagesCollide(nave\img,nave\px,nave\py,0 ,This\img,This\px,This\py,0) Then Return 1 Next End Function Function GameOver() Cls Text 350, 290, "GAME OVER" Text 310, 310, "Voc fez " + PONTOS + " Pontos" Flip Delay(3000) Cls Flip AddScore(PONTOS) ExibeScores() End End Function

Veja que foram poucas as alteraes sofridas no arquivo principal, isso porque ajustamos o arquivo includo para funcionar apenas com duas interfaces. A primeira coisa que obrigatoriamente temos que fazer incluir o arquivo de scores.
Include "Scores.bb"

A partir disso, as alteraes s ocorreram na funo GameOver(). Primeiro invocamos a interface de adio de escores. Esse mtodo tem a responsabilidade de verificar se a pontuao vai entrar nos escores e se isso for verdadeiro, pegar o nome do jogador e inserir nome e pontos no ranking. Para isso,
43

ele s precisa receber os pontos atuais do jogador.


AddScore(PONTOS)

O Segundo mtodo invocado o de exibir a pontuao.


ExibeScores()

Essas foram todas as alteraes que tivemos que fazer em nosso arquivo principal do jogo. Simples no ? Vamos agora as alteraes no arquivo "Scores.bb". Arquivo "Scores.bb"
Global nome1$ Global ponto1 Global nome2$ Global ponto2 Global nome3$ Global ponto3 Global nome4$ Global ponto4 Global nome5$ Global ponto5 ;******************************* INTERFACE ************************************* Function AddScore(pontos) LerScores() If pontos > ponto5 Text 200, 250, "Voc est entre as melhores pontuaes!" Locate 200, 300 seunome$ = Input$("Digite seu nome: ") GravarScores(seunome$, pontos) EndIf Cls Flip End Function Function ExibeScores() LerScores() Cls Flip Color 0,255,0 Text 250, 220, "********* MELHORES PONTUAES *********" Color 255,255,255 If ponto1 > 0 Then Text 250,250, nome1$ + " " + ponto1 If ponto2 > 0 Then Text 250,280, nome2$ + " " + ponto2 If ponto3 > 0 Then Text 250,310, nome3$ + " " + ponto3 If ponto4 > 0 Then Text 250,340, nome4$ + " " + ponto4 If ponto5 > 0 Then Text 250,370, nome5$ + " " + ponto5 Color 0,255,0 Text 250, 410, "*************************************** " Flip Delay(5000)

End Function ;******************************* PRIVADOS ************************************* Function LerScores() If FileType("f15.data") aberto = ReadFile ("f15.data") nome1$ = ReadString(aberto) ponto1 = ReadInt(aberto) nome2$ = ReadString(aberto) ponto2 = ReadInt(aberto) nome3$ = ReadString(aberto) ponto3 = ReadInt(aberto) nome4$ = ReadString(aberto) ponto4 = ReadInt(aberto) nome5$ = ReadString(aberto) ponto5 = ReadInt(aberto) CloseFile(aberto) EndIf End Function Function GravarScores(jogador$, pontos) ;pegando os dados atuais do arquivo If FileType("f15.data") aberto = ReadFile ("f15.data") play1$ = ReadString(aberto) score1 = ReadInt(aberto) play2$ = ReadString(aberto) score2 = ReadInt(aberto) play3$ = ReadString(aberto) score3 = ReadInt(aberto) play4$ = ReadString(aberto) score4 = ReadInt(aberto) play5$ = ReadString(aberto) score5 = ReadInt(aberto) CloseFile(aberto) EndIf ; fasendo seleo de dados If pontos > score5 score5 = pontos play5$ = jogador$ EndIf If pontos > score4 score5 = score4 play5$ = play4$ score4 = pontos play4$ = jogador$ EndIf If pontos > score3 score4 = score3 play4$ = play3$ score3 = pontos play3$ = jogador$ EndIf If pontos > score2 score3 = score2 play3$ = play2$ score2 = pontos play2$ = jogador$ EndIf If pontos > score1 score2 = score1 play2$ = play1$

44

score1 = pontos play1$ = jogador$ EndIf ; gravar dodos depois da seleo aberto = WriteFile("f15.data") WriteString(aberto, play1$) WriteInt(aberto, score1) WriteString(aberto, play2$) WriteInt(aberto, score2) WriteString(aberto, play3$) WriteInt(aberto, score3) WriteString(aberto, play4$) WriteInt(aberto, score4) WriteString(aberto, play5$) WriteInt(aberto, score5) CloseFile(aberto) End Function

A primeira coisa que tivemos que fazer para criar o nosso componente de escores foi criar uma interface para adicionar escores.
Function AddScore(pontos) LerScores()

Text 250, 220, "********* MELHORES PONTUAES *********" Color 255,255,255 If ponto1 > 0 Then Text 250,250, nome1$ + " " + ponto1 If ponto2 > 0 Then Text 250,280, nome2$ + " " + ponto2 If ponto3 > 0 Then Text 250,310, nome3$ + " " + ponto3 If ponto4 > 0 Then Text 250,340, nome4$ + " " + ponto4 If ponto5 > 0 Then Text 250,370, nome5$ + " " + ponto5 Color 0,255,0 Text 250, 410, "*************************************** " Flip Delay(5000)

Veja que essa funo recebe apenas a pontuao do jogador atual. A primeira coisa que ela faz carregar os dados do arquivo de escores por meio da funo LerScores(); esses dados sero armazenados nas variveis globais.
If pontos > ponto5 Text 200, 250, "Voc est entre as melhores pontuaes!" Locate 200, 300 seunome$ = Input$("Digite seu nome: ") GravarScores(seunome$, pontos) EndIf

Logo em seguida, feita a verificao se a pontuao do jogador atual superior a pontuao do ultimo colocado do ranking de escores pontos > ponto5, pois essa a condio para que ele entre nesse ranking. Caso isso seja verdadeiro, exibe-se uma mensagem de aviso e pede para que ele entre com o seu nome. Para coletar o nome usamos o comando Input$ e o nome fornecido ficar armazenado na varivel seunome$. Assim, enviamos nome e pontos para serem gravados GravarScores(seunome$, pontos). A outra alterao no nosso componente de controle de escores foi a criao de uma interface para exibir os escores.
Function ExibeScores() LerScores() Cls Flip Color 0,255,0

Veja que ela bem simples, apenas usa a funo LerScores() para carregar os dados atuais de escores para as variveis globais e em seguida exibe esses dados na tela. Ela tambm usa o metodo Delay() para fazer com que o programa de uma pausa de 5 segundos para dar tempo de lermos os escores. As funes LerScores() e GravarScores() no sofreram alteraes por isso no iremos comentar. Caso tenha alguma dvida, consulte a explicao do exemplo 32. Pronto, agora o seu jogo est completo! E alm disso voc aprendeu a fazer na prtica reuso de software, criao de componente e incluso de arquivo. Alm de se tornar um desenvolvedor de jogos, voc vai acabar virando um grande arquiteto de software. ALELUIA!!!! Finalmente chegamos ao fim da teoria de programao. Voc j deve estar cansado de ficar exibindo mensagens na tela. Infelizmente essa maneira a mais fcil e rpida de ensinar o bsico da programao. Se para cada comando novo tivesse que criar um jogo... A partir do prximo bloco trataremos apenas sobre jogos, fundamentos e prticas. Se voc chegou at aqui cheio de dvidas, no se preocupe isso sinal de que voc humano e ter muitas maneiras de solucionar esses problemas. Se voc conseguiu
45

compreender tudo, parabns voc um gnio e provavelmente ser um dos prximos integrantes da EA GAMES ou ento fundador

da prxima empresa que ir revolucionar o mundo dos jogos.

Anotaes
_______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________ _______________________________________________________________________________________

46