Vous êtes sur la page 1sur 48

7. JOGOS 3D Chegamos agora parte que provavelmente voc estava aguardando.

. No de se estranhar afinal, com as engines 3D, ns temos total liberdade de movimento e infinitas possibilidades em termos de jogabilidade. Eu me lembro at hoje dos primeiros jogos 3D que joguei: Wolfenstein 3D, Marathon e Doom. A sensao de sair dos limites tradicionais de um jogo 2D foi incrvel. Como possua um computador Apple, tive a exclusividade de conferir os incrveis grficos de Marathon que deixavam qualquer concorrente no chinelo. A partir desse momento voc vai poder entrar nesse seletssimo submundo: o dos desenvolvedores de incrveis jogos 3D. Graas ao poder e a simplicidade do Blitz3D isso vai se dar de forma simples e sem traumas. Vamos l! Introduo a 3D Enquanto no modo grfico 2d trabalhvamos com apenas duas coordenadas x e y, uma vertical e outra horizontal, no modo 3d temos a adio de mais um eixo o eixo z, de profundidade. Grficos 2d Grficos 3d

matemticos necessrios para se compor um plano.


Malha com 3 vrtices e 1 tringulo Malha com 4 vrtices e 2 tringulos

Dessa forma, se nos jogos 2d tnhamos que controlar s 2 variveis de posicionamento, em um jogo 3d temos 3 variveis de posicionamento. Mas no se preocupe, pois isso no significa que necessariamente voc ter 50% a mais de trabalho. A criao de um jogo 3d totalmente diferente da de um jogo 2d. Enquanto em jogos 2d usamos bitmaps para criar praticamente todo o jogo, em uma engine 3d usamos malhas 3d, os objetos 3d. Um objeto 3d normalmente feito de um ou mais tringulos. As placas aceleradoras grficas 3d usam basicamente tringulos para comporem a imagem, pois 3 vrtices so a menor quantidade de dados

Veja que de fato a composio de malhas 3d com tringulos a mais simples, e a que pode render maior capacidade de processamento, pois a cada novo vrtice criado, uma nova face (tringulo) tambm pode ser criada. Cada vrtice possui uma coordenada x, y e z e pode ser manipulado individualmente. O fato de os vrtices possurem a coordenada z que possibilita a criao de objetos 3d, pois do contrrio s poderiam ser criados objetos planos. Abaixo voc pode ver como o computador cria os cenrios 3d por meio de tringulos e vrtices. As imagens foram tiradas do projeto Tucano 3d, de minha autoria.

modo normal modo wire (mostra a estrutura)

Como voc pode ver, tudo no jogo feito por tringulos, que so preenchidos por mapeamento de textura. Mas voc no precisa se preocupar com isso se no quiser. O Blitz3D d a possibilidade de trabalhar com objetos 3d tanto em modo bem primrio, manipulando vrtice por vrtice, como de modo bem mais genrico, com modelos criados em programas externos, onde voc s precisa de uma linha de cdigo para carreg-los e mais uma linha para fazer com que acione as suas animaes. Modo grfico A engine 3d do Blitz roda em modo grfico prprio, assim, antes de qualquer outra coisa, devemos configurar o modo grfico para comear a trabalhar com aplicaes 3d. O exemplo abaixo mostra como fazer isso. Exemplo 1
Graphics3D 640,480 SetBuffer BackBuffer() End

Graphics3D 640,480 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() WaitKey End

Ai est o nosso programa mnimo. A primeira coisa que fizemos foi definir o modo grfico:
Graphics3D 640,480

Logo em seguida configuramos o modo de double buffer, criando um buffer para desenho. Assim os grficos vo ficar com melhor aparncia e mais suaves.
SetBuffer BackBuffer()

Jamais poderemos esquecer de criar uma cmera. As cmeras so nossos olhos em uma aplicao 3d. Tudo o que vemos em um ambiente desse tipo capitado pela cmera, sem ela s veremos uma tela preta.
camera=CreateCamera()

Criamos a cmera com o comando CreateCamera() e colocamos sua referncia (handle) em uma varivel, no caso camera.
light=CreateLight()

Veja que o comando para iniciar o modo grfico 3D Graphics3D. Esse comando semelhante ao comando de modo grfico 2d, ele tambm aceita as configuraes de paleta de cores e de modo da janela. Veja um novo exemplo. Exemplo 2
Graphics3D 800,600, 32, 2 SetBuffer BackBuffer() WaitKey End

Nessa linha geramos a iluminao por meio da criao de uma lmpada. Veja que tambm declaramos uma varivel para ela. O Blitz3D j inicializa com uma iluminao ambiente default, mas em tom cinza, por isso devemos criar uma lmpada.
WaitKey End

Agora o programa roda em modo janela com 32 bits de profundidade de cores. O mnimo necessrio Para comearmos a trabalhar com visualizaes de objetos 3d existem configuraes mnimas necessrias do programa. No podemos trabalhar em modo 3d sem iniciar o modo grfico 3d. No podemos exibir um objeto 3d na tela se no existir uma cmera na aplicao e nada iremos enxergar se o ambiente estiver em profunda escurido. Assim abaixo temos os requisitos para iniciar uma aplicao 3d: 1. configura o modo grfico 2. criar uma cmera 3. criar iluminao Vamos agora a um exemplo que contenha esses requisitos mnimos. Exemplo 3

Aqui aguardamos at que uma tecla seja pressionada para encerrar a aplicao. Ns j temos uma aplicao completa, mas ainda no visualizamos nada. No prximo exemplo carregamos e exibimos um modelo 3d para que voc veja o efeito desses comandos em ao. O modelo 3d vem junto com o Blitz3D, mas o coloquei na pasta dos exemplos para facilitar nossa vida. Os comando usados sero explicados mais frente.

vrtices. a primitiva ideal para quem deseja construir algo extremamente leve. S devemos ter o cuidado de deixar a sua face voltada para o lado correto. Tambm a primitiva ideal para criar suporte a restrio de movimentos ou colises. Para isso o deixamos invisvel e verificamos se um objeto colide com ele. Vamos a um exemplo de criao de um plano. Exemplo 5
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,1,0 light=CreateLight() plano= CreatePlane() RenderWorld Flip WaitKey End

Exemplo 4
Graphics3D 640,480 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() carro=LoadMesh("midia/caro.3ds") RotateEntity carro, 0, 30, 0 PositionEntity carro,0,-200,700 While Not KeyHit(1) y = y + 1 RotateEntity carro, 0, y, 0 RenderWorld Flip Wend End

Cubo Um cubo formado por 6 faces, assim ele possui 12 tringulos na sua composio. a primitiva mais bsica para compor objetos com volume, como paredes, muros, caixas, escadas, etc. Exemplo 6
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() cubo= CreateCube() PositionEntity cubo,2,0,6 RenderWorld Flip WaitKey End O comando CreateCube() cria

Para que os objetos 3d apaream na tela necessrio ordenar ao blitz que renderize os objetos. Isso feito nessa linha:
RenderWorld

Com esse comando, renderizamos os objetos 3d e colocamos essa imagem no buffer de imagem. Para que eles apaream no monitor devemos transferir a imagem para o buffer do monitor.
Flip

Isso foi incrvel, no foi? PRIMITIVAS O blitz possui comandos para criar 5 tipos de primitivas grficas 3d: planos, cubos, esferas, cilindros e cones. Essas primitivas podem ser muito teis para criao de cenrios caso voc no possua ou no saiba usar um modelador 3d. Tambm podem ser usadas para diversas finalidades, como ajudar no controle de um objeto 3d, restrio de movimentos, ou auxiliar na deteco de colises. Plano O plano a primitiva mais bsica e composto apenas de 2 tringulos e 4

um cubo de dimenses 2,2,2 e na posio 0,0,0. Tambm podemos criar uma hierarquia passando um objeto pai como referncia com a sintaxe CreateCube(objetopai). Dessa forma o cubo criado ficar ligado ao objeto pai. Usamos o comando PositionEntity para colocar o cubo em um local que seja visvel cmera, seno no iramos visualizar o objeto. Esfera Com o comando CreateSphere() podemos criar esferas no Blitz3D. O comando padro, sem parmetros, cria uma esfera de raio igual a 1 e na posio 0,0,0. A esfera criada ter 8 segmentos e 224 polgonos de composio.

Tambm podemos passar como parmetro a quantidade de segmentos que a esfera dever possuir e/ou um objeto para criar uma hierarquia. Exemplo 7
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() esfera1 = CreateSphere() PositionEntity esfera1,3,0,6 esfera2 = CreateSphere(3) PositionEntity esfera2,-3,0,6 esfera3 = CreateSphere(16, esfera1) PositionEntity esfera3,-3,0,0 RenderWorld Flip WaitKey End

ci = CreateCylinder() PositionEntity ci,2,0,5 ci2 = CreateCylinder(32) PositionEntity ci2,-2,0,5 RotateEntity ci2, 90,0,0 RenderWorld Flip WaitKey End

Cones Para criar cones, usamos o comando CreateCone(). Esse comando possui a mesma assinatura do CreateCylinder, assim aceita os parmetros: segmentos, slido e hierarquia. Exemplo 9
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() cone = CreateCone(32) PositionEntity cone,1,0,3 RenderWorld Flip WaitKey End

Na primeira esfera que criamos usamos o comando padro, sem passar parmetros, assim ser construda uma esfera de 8 segmentos.
esfera1 = CreateSphere()

Para nossa segunda esfera, estamos passando o parmetro 3, assim iremos construir uma esfera de 3 segmentos.
esfera2 = CreateSphere(3)

Por fim, passamos para a terceira esfera os parmetros 16, esfera1, assim, a terceira esfera a ser criada, ter alta resoluo, pois formada por 16 segmentos, e ser filha da primeira esfera.
esfera3 = CreateSphere(16, esfera1)

A filiao dessa esfera para com a esfera 1, d a ela a posio geogrfica relativa de seu objeto pai, assim, para coloc-la ao centro, tivemos que fazer compensaes no comando de posicionamento.
PositionEntity esfera3, -3, 0, 0

Pintar Objetos 3d Podemos criar um pincel no Blitz3D e com ele podemos pintar objetos 3d. O primeiro passo criar um pincel (brush) como o comando CreateBrush() e em seguida pintamos o objeto com esse pincel com o comando PaintMesh(). Exemplo 10
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateSphere(32) PositionEntity ob,1,0,3 pincel = CreateBrush() BrushColor pincel, 255,0,0 PaintMesh ob, pincel RenderWorld Flip WaitKey End

Cilindros Para criar cilindros usamos o comando CreateCylinder(). Por padro, o comando cria um cilindro de 8 segmentos slido. Mas esse comando tambm permite passarmos parmetros de segmentos, slido e hierarquia. Assim, a assinatura do comando CreateCylinder(sementos, slido, hierarquia). O parmetro deve ser configurado em 1 para slidos e 0 para criar um tubo. Exemplo 8
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight()

A primeira coisa que fizemos foi criar o pincel, o brush.


pincel = CreateBrush()

Em segundo momento, definimos uma cor para o pincel. Escolhemos a cor vermelha (255,0,0).
BrushColor pincel, 255,0,0

O ultimo passo pintar um objeto com o pincel.


PaintMesh ob, pincel

TEXTURAS Texturas so imagens que so aplicadas nas superfcies dos objetos 3d. Uma textura mapeada na face de um objeto, criando um nvel muito alto de realismo. Mas frente iremos estudar tcnicas avanadas de texturizao. Nesse momento vamos aprender a carregar uma textura e aplicar a mesma em um objeto 3d. Para carregar uma textura usamos o comando LoadTexture() e para aplicar a mesma em um objeto usamos o comando EntityTexture. Veja o exemplo abaixo. Exemplo 11
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() textura = LoadTexture("midia\parede.jpg") cubo = CreateCube() PositionEntity cubo,0,0,4 EntityTexture cubo, textura While Not KeyHit(1) TurnEntity cubo, 0, 1, 0 RenderWorld Flip Wend End

colocar um fundo preto. Da basta colocarmos uma frag de carregamento da textura para 2, isso , com canal alfa. Quando texturizarmos um objeto esse ficar transparente na parte escura da textura. Veja o exemplo a seguir Exemplo 12
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,2,0 light=CreateLight() cerca = LoadTexture("midia\alfa.png",2) ScaleTexture cerca, .2, 1 Bloco = CreateCube() ScaleEntity Bloco, 3,1.5, 0.2 PositionEntity bloco, 0, 1.1, 7 b = CreateBrush() BrushColor b, 255, 0, 0 PaintMesh bloco, b EntityTexture bloco, cerca RenderWorld Flip WaitKey End

Veja que ao carregarmos a textura com o comando LoadTexture colocamos mais um parmetro, a flag 2.
cerca = LoadTexture("midia\alfa.png",2)

O primeiro passo carregar uma textura de um arquivo externo para uma varivel
textura = LoadTexture("midia\parede.jpg")

Para que a cerca no ficasse totalmente branca, colorimos o modelo com um brush.
b = CreateBrush() BrushColor b, 255, 0, 0 PaintMesh bloco, b

Depois disso criamos o cubo, o objeto que receber a textura.


cubo = CreateCube() PositionEntity cubo,0,0,4

Para aplicar a textura com canal alfa no objeto no h nenhuma novidade, segue-se o padro.
EntityTexture bloco, cerca

Por fim vamos aplicar a textura no cubo


EntityTexture cubo, textura

Dentro do loop estamos rotacionando o cubo no eixo y com o comando TurnEntity.


TurnEntity cubo, 0, 1, 0

Texturas com canal alpha Assim como fazemos mscaras com imagens em jogos 2d para remover o fundo de uma imagem, tambm podemos fazer algo semelhante com texturas. Imagine que voc tem um ponto de seu jogo que a lateral de um ambiente protegida com uma cerca ou uma grade. Se voc fosse criar isso manualmente num modelador 3d voc gastaria muito tempo e o resultado seria um modelo de alta complexidade que com certeza sobrecarregaria o seu jogo. Uma outra soluo para isso criar uma textura com o desenho da cerca ou grade, e

Ajustar texturas muito difcil uma textura se ajustar perfeitamente a um modelo na qual ser aplicada. Normalmente deveremos colocar vrias cpias da textura alinhadas para dar um efeito maior de realismo. Um exemplo disso quando vamos criar objetos grades como paredes e pisos. Se colocarmos apenas uma textura, ela ser esticada e ficar disforme e desproporcional. Isso pode ser corrigindo com o comando ScaleTexture. Esse comando ajusta o quantidade de instncias da textura que devero ser aplicadas em um objeto. Como o objeto mapeado por completo, quanto menor o tamanho da textura, mais ocorrncias dela aparecero em uma face do objeto.

Uma ocorrncia por face => ScaleTexture


textura, 1, 1

End

Uma ocorrncia horizontal e 2 verticais =>


ScaleTexture textura, 1, 0.5

Dez ocorrncias em todas as faces =>


ScaleTexture textura, 0.1, 0.1

Coordenadas Tambm podemos ajustar o posicionamento da textura no objeto por meio do comando PositionTexture. Por meio dele podemos ajustar a posio x e y da textura no objeto. Exemplo 14
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() Bloco1 = CreateCube() ScaleEntity Bloco1, 5, 4, 1 PositionEntity Bloco1, 0, 0, 7 tex1= LoadTexture("midia\agua.png") ScaleTexture tex1, .2, .2 EntityTexture bloco1, tex1 While Not KeyHit(1) x# = x# + 0.005 PositionTexture tex1, x#, y RenderWorld Flip Wend End

Veja o exemplo abaixo onde criamos vrios cubos do mesmo tamanho, mas configuramos as texturas com escalas diferentes.

Veja que a assinatura desse comando : PositionTexture textura, coordenada x, coordenada y Texturas animadas Assim como podemos carregar imagens animadas, tambm podemos carregar texturas animadas. Para isso usamos o comando LoadAnimTexture(). Sua sintaxe quase igual a do comando LoadAnimImage(), mas com a diferena que tambm devemos colocar o flag de textura. Confira:
LoadAnimTexture(arquivo, flag, largura, altura, primeiro frame, frames)

Exemplo 13
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() Bloco1 = CreateCube() ScaleEntity Bloco1, 2, 2, 1 PositionEntity Bloco1, -3, -2.2, 7 Bloco2 = CreateCube() ScaleEntity Bloco2, 2, 2, 1 PositionEntity Bloco2, 3, -2.2, 7 Bloco3 = CreateCube() ScaleEntity Bloco3, 2, 2, 1 PositionEntity Bloco3, -3, 2.2, 7 Bloco4 = CreateCube() ScaleEntity Bloco4, 2, 2, 1 PositionEntity Bloco4, 3, 2.2, 7 tex1= LoadTexture("midia\parede.jpg") tex2= LoadTexture("midia\parede.jpg") tex3= LoadTexture("midia\parede.jpg") tex4= LoadTexture("midia\parede.jpg") ScaleTexture tex1, 1, 1 EntityTexture bloco1, tex1 ScaleTexture tex2, .5, 1 EntityTexture bloco2, tex2 ScaleTexture tex3, .5, .5 EntityTexture bloco3, tex3 ScaleTexture tex4, .2, .2 EntityTexture bloco4, tex4 RenderWorld Flip WaitKey

Veja o exemplo abaixo Exemplo 15


Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() Bloco1 = CreateCube() ScaleEntity Bloco1, 5, 4, 1 PositionEntity Bloco1, 0, 0, 7 tex1= LoadAnimTexture("midia\aguaani.png",1,15 0,150,0,2) ScaleTexture tex1, .2, .2 While Not KeyHit(1) x = x + 1 If x = 10 x = 0 frame = frame + 1 If frame = 2 Then frame = 0 EndIf

EntityTexture bloco1, tex1, frame RenderWorld Flip Wend End

Por isso que, como mostrado na linha abaixo, aplicamos essas camadas na textura.
EntityTexture bloco1, tex1, 0,

A textura bsica aplicada como camada 0.


If KeyDown(57) Then EntityTexture bloco1, filtro, 0, 1

Camadas de texturas Um dos maiores problemas no mapeamento de texturas que quando temos que repetir vrias vezes a mesma textura para preencher corretamente um objeto, causamos a sensao de uniformidade e fica visvel que o que vemos a repetio de vrias imagens. No mundo real as coisas no so uniformes, elas tm disformidades aleatrias e o mapeamento de textura causa o efeito contrrio, o de uniformidade. Para resolver isso podemos sobrepor camadas de texturas, assim devemos colocar uma textura para fazer um mapeamento de detalhe sobre a textura base, tirando o efeito de uniformidade causado pela repetio dessa. O ideal que a textura filtro tenha uma escala de 1x1 para no causar repeties. O exemplo abaixo demonstra um mapeamento de textura com uma s camada e o mapeamento com o uso de uma textura para gerar detalhes. Exemplo 16
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() Bloco1 = CreateCube() ScaleEntity Bloco1, 5, 4, 1 PositionEntity Bloco1, 0, 0, 7 tex1= LoadTexture("midia\pedra.jpg") ScaleTexture tex1, .2, .2 EntityTexture bloco1, tex1, 0, 0 filtro= LoadTexture("midia\filtro.jpg") While Not KeyHit(1) If KeyDown(57) Then EntityTexture bloco1, filtro, 0, 1 RenderWorld Text 70, 10, "PRESSIONE SPACE PARA APLICAR FILTRO" Flip Wend End

Se apertarmos a barra de espao, ento aplicamos a camada seguinte, a de detalhamento. O Blitz3D suporta at 8 camadas de texturas, que vo da camada 0 at a camada 7. Aprender a usar corretamente esse recurso gera objetos de alta qualidade grfica. Cenrios com primitivas Caso voc no possua um modelador 3d, ou no saiba usar um, voc pode criar cenrios para seus jogos com primitivas grficas texturizadas do blitz, veja o exemplo abaixo. Exemplo 17
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,2,0 light=CreateLight() tchao = LoadTexture("midia\chao.jpg") ScaleTexture tchao, .05, .05 tparede = LoadTexture("midia\pedra.jpg") ScaleTexture tparede, .05, .5 tbloco = LoadTexture("midia\parede.jpg") ScaleTexture tparede, .05, .5 chao = CreateCube() ScaleEntity chao, 20,0.2, 20 PositionEntity chao, -10, 0, -10 parede1 = CreateCube() ScaleEntity parede1, 20,2, 0.5 PositionEntity parede1, -10, 2, 10 Bloco = CreateCube() PositionEntity bloco, 2, 1.1, 7 EntityTexture chao, tchao EntityTexture parede1, tparede EntityTexture bloco, tbloco While Not KeyHit(1) RenderWorld Flip Wend End

Veja o resultado:

Veja que para aplicar camadas, devemos configurar a aplicao de cada textura com uma camada de acordo com a assinatura completa do comando EntityTexture, conforme abaixo: EntityTexture objeto, varivel, frame, camada

O prximo exemplo usa o comando de escalonamento dos vrtices: ScaleMesh Exemplo 19


Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateSphere(32) PositionEntity ob,0,0,5 x# = 1 While Not KeyHit(1) Text 10, 10, "Aperte Space para escalonar" If KeyHit(57) x# = x# + 0.2 ScaleMesh ob, x#, x#, x# EndIf RenderWorld Flip Wend End

TRANSFORMAES Os objetos 3d so passveis de vrias transformaes como escalonamento (alterar o tamanho), posicionamento, rotao, movimentao, etc. Vamos estudar as principais transformaes. Escalonar Escalonar um objeto 3d alterar suas escalas nos eixos x, y e z. Podemos aumentar ou diminuir um objeto em qualquer um desses trs eixos. Podemos escalonar um objeto com o comando ScaleEntity ou escalonar os vrtices dele por meio do comando ScaleMesh. Vamos a um exemplo. Exemplo 18
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateSphere(32) PositionEntity ob,0,0,5 x# = 1 While Not KeyHit(1) Text 10, 10, "Aperte Space para escalonar" If KeyHit(57) x# = x# + 0.2 ScaleEntity ob, x#, x#, x# EndIf RenderWorld Flip Wend End

Rotao Existem trs comando que possibilitam fazer rotao em um objeto 3d: RotateMesh, TurnEntity e RotateEntity. Embora cada um deles se dispe mesma finalidade, o fazem de maneiras diferentes, causando efeitos secundrios diferentes. O primeiro que veremos em ao o comando RotateMesh. A peculiaridade desse comando o fato de rotacionar apenas os vrtices do objeto. Embora isso cause a aparncia visual de que o objeto todo foi rotacionado, seus dados lgicos no sofrem modificaes, isso , a orientao absoluta, suas faces continuam voltadas para o mesmo lugar. Ele tambm funciona por orientao relativa, isso , o valor que passarmos a ele ser calculado a partir do angulo atual do objeto e no de seu posicionamento relativo s coordenadas da engine. Isso significa que no precisamos criar um contador para criar um efeito de rotao contnua. Basta passar um pequeno valor e dar loops. Exemplo 20
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateCube() PositionEntity ob,0,0,3 pincel = CreateBrush() BrushColor pincel, 255,0,0 PaintMesh ob, pincel While Not KeyHit(1) RotateMesh ob, 0, 1, 0 RenderWorld

Veja que podemos escalonar um objeto nos seus trs eixos:


ScaleEntity ob, x#, x#, x#

Caso voc deseje escalonar em um s eixo, basta deixar os demais com o valor 1, que corresponde ao tamanho real, sem escala. Substitua o trecho de cdigo acima como na linha abaixo e faa um teste:
ScaleEntity ob, x#, 1, 1

Text 10, 10, "ANGULO Y: " + EntityYaw#(ob) Flip Wend End

Veja que no precisamos usar contador para criar esse efeito.


RotateMesh ob, 0, 1, 0

O comando RotateEntity gera efeitos de rotao absolutos, relativos ao cenrio, isso , relativos orientao da engine. Ele muito usado para colocar um objeto em um ngulo especfico em relao orientao do cenrio Exemplo 22
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateCube() PositionEntity ob,0,0,3 While Not KeyHit(1) RotateEntity ob, 0, 45, 0 RenderWorld Text 10, 10, "ANGULO Y: " + EntityYaw#(ob) Flip Wend End

A segunda coisa a considerar o fato que a rotao dos vrtices no alterou a orientao do objeto que continua com a face voltada para o mesmo lugar. A linha abaixo demonstra isso, pois o comando EntityYaw#() retorna o ngulo y atual de um objeto qualquer.
Text 10, 10, "ANGULO Y: " + EntityYaw#(ob)

Veja que essa linha de informao foi colocada aps o comando de Render e antes do Comando Flip. Isso significa que s colocamos imagens 2d no buffer depois de todo o cenrio 3d ser renderizado, seno esses grficos vo ser subscritos pela composio grfica do cenrio.
RenderWorld Text 10, 10, "ANGULO Y: " + EntityYaw#(ob) Flip O comando TurnEntity rotaciona

o objeto inteiro, portanto tudo que est nele. Assim tambm sua orientao ser alterada. Ele tambm possui sistema de rotao relativa, isso , o numero que especificarmos que ser o ngulo de rotao ser somado ao ngulo atual do objeto, tambm desprezando o uso de contador para criar rotao continua. Nosso prximo exemplo semelhante ao anterior, mas agora perceba que o ngulo Yaw (y) sofrer alteraes. Exemplo 21
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateCube() PositionEntity ob,0,0,3 pincel = CreateBrush() BrushColor pincel, 255,0,0 PaintMesh ob, pincel While Not KeyHit(1) TurnEntity ob, 0, 1, 0 RenderWorld Text 10, 10, "ANGULO Y: " + EntityYaw#(ob) Flip Wend End

Posicionamento Para posicionar um objeto usamos o comando PositionEntity. Com ele colocamos o objeto em uma posio absoluta do cenrio. o comando perfeito para fazer ajuste de personagens e objetos ao carregar um jogo ou uma fase. Exemplo 23
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateCube() PositionEntity ob,0,0,3 While Not KeyHit(1) x = Rnd(-2,2) y = Rnd(-2,2) z = Rnd(2, 20) If KeyHit(57) Then PositionEntity ob, x, y, z RenderWorld Text 10,10, "Pressione SPACE para posicionar em local aleatrio" Flip Wend End

Mover Para movermos objetos 3d podemos fazer uso de dois comandos distintos: TranslateEntity e MoveEntity. Esses comandos tm efeitos diferentes, pois enquanto um deles move um objeto de acordo com a orientao universal, o outro o move de acordo com sua prpria orientao. Assim, o primeiro ideal para mover objetos e o segundo melhor para controlar personagens.

O comando TranslateEntity move um objeto em um dos seus trs eixos relativos ao ambiente 3d. Isso quer dizer que mesmo que ele seja rotacionado, sempre vai se mover para o mesmo lugar enquanto os parmetros do comando no forem alterados. Esse o comando padro para mover objetos inanimados que tem sua trajetria definida por vetores. Veja um exemplo Exemplo 24
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateCube() PositionEntity ob,0,0,20 While Not KeyHit(1) If KeyDown(200) Then TranslateEntity ob, 0, 0, .1 If KeyDown(208) Then TranslateEntity ob, 0, 0, -.1 If KeyDown(203) Then TranslateEntity ob, -.1, y, 0 If KeyDown(205) Then TranslateEntity ob, .1, y, 0 If KeyDown(57) Then TurnEntity ob, 0, 1, 0 RenderWorld Text 10,10, "SPACE -> Rotaciona; SETAS > movem" Text 10,25, "PERMANEA COM O SPACE PRESSIONADO E VERIFIQUE" Text 10,37, "QUE A ROTAO NO MUDA A DIREO" Flip Wend End

Com o comando MoveEntity podemos controlar melhor objetos animados, principalmente os personagens principais. Quando um carro faz uma ligeira curva ele deixa de ir para uma direo e passa a se mover para outra, para onde a sua frente aponta. Com o comando do exemplo anterior ficaria muito complicado fazer isso, afinal, quando ele rotaciona o objeto vai para a mesma direo. Mas com o uso de MoveEntity o movimento do objeto depende de sua orientao. Se definirmos que ele se mover para frente, quando ele rotaciona, sua frente altera de posio e seu movimento obedece essa mudana de sentido. Veja o exemplo anterior agora usando o MoveEntity. Exemplo 25
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight() ob = CreateCube() PositionEntity ob,0,0,20 While Not KeyHit(1) If KeyDown(200) Then MoveEntity ob, 0, 0, .1 If KeyDown(208) Then MoveEntity ob, 0, 0, -.1 If KeyDown(203) Then MoveEntity ob, -.1, y, 0 If KeyDown(205) Then MoveEntity ob, .1, y, 0 If KeyDown(57) Then TurnEntity ob, 0, 1, 0 RenderWorld Text 10,10, "SPACE -> Rotaciona; SETAS > movem" Text 10,25, "PERMANEA COM O SPACE PRESSIONADO E VERIFIQUE" Text 10,37, "COMO A ROTAO ALTERA AGORA A DIREO" Flip Wend End

Na linha abaixo, quando pressionamos a seta para cima, movemos o objeto em um dcimo de unidades para o fundo da tela.
If KeyDown(200) Then TranslateEntity ob, 0, 0, .1

J a linha seguinte faz o efeito inverso: se pressionarmos a seta para baixo, o objeto se aproxima da tela.
If KeyDown(208) Then TranslateEntity ob, 0, 0, -.1

As prximas linhas controlam os movimentos laterais, dai so implementadas com o uso das setas para as laterais.
If KeyDown(203) Then TranslateEntity ob, -.1, y, 0 If KeyDown(205) Then TranslateEntity ob, .1, y, 0

Por fim, para vermos como difere do outro comando, usamos a barra de espaos para rotacionar o objeto.
If KeyDown(57) Then TurnEntity ob, 0, 1, 0

MODELOS 3D O Blitz3D carrega trs tipos de modelos 3d: modelos .3ds nativos do Autodesk 3ds Max, modelo .x que so nativos do Directx e modelos .b3d os modelos padres do prprio Blitz3D. Controlamos todos esses modelos usando os mesmos comandos. Para carregar um modelo 3d basta usar o comando LoadMesh. Veja um exemplo simples. Exemplo 26
Graphics3D 800,600

SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,0,-30 light=CreateLight() caixa = LoadMesh("midia\supplies.x") RenderWorld Flip WaitKey End

Ao carregarmos um modelo 3d ele automaticamente posicionado nas coordenadas 0,0,0 Como voc pode perceber, a textura adicionada automaticamente ao modelo 3d, mas caso ocorra algum problema voc tambm pode carregar e aplicar uma textura ao se modelo 3d. No exemplo abaixo, aplicamos uma segunda textura no modelo 3d. Exemplo 27
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,0,-30 light=CreateLight() caixa = LoadMesh("midia\supplies.x") tex = LoadTexture("midia\parede.jpg",2) EntityTexture caixa, tex, 0, 1 RenderWorld Flip WaitKey End

If KeyDown(208) Then TranslateEntity caixa, 0, -.1, 0 If KeyDown(203) Then TranslateEntity caixa, -.1, 0, 0 If KeyDown(205) Then TranslateEntity caixa, .1, 0, 0 Else If KeyDown(200) Then TranslateEntity caixa2, 0, .1, 0 If KeyDown(208) Then TranslateEntity caixa2, 0, -.1, 0 If KeyDown(203) Then TranslateEntity caixa2, -.1, 0, 0 If KeyDown(205) Then TranslateEntity caixa2, .1, 0, 0 EndIf RenderWorld Color 255,255,255 Text 10,10, "SPACE -> MUDA OBJETO SELECIONADO; SETAS-> MOVE" Color 255,0,0 If ob Text 10, 25, "Objeto Atual: * PAI *" Else Text 10, 25, "Objeto Atual: * FILHO *" EndIf Flip Wend WaitKey End

Veja que carregamos a segundo textura com a flag 2 de canal alpha para dar uma melhor composio de imagem:
tex = LoadTexture("midia\parede.jpg",2)

O comando LoadMesh aceita um segundo parmetro que para criar uma hierarquia. O modelo passado como parmetro ser o modelo pai. Se o modelo pai se move o filho se move tambm. Se o modelo filho se move o pai ficar parado. Somente os comandos sobre o objeto pai iro refletir na hierarquia. Veja isso no prximo exemplo. Exemplo 28
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,0,-80 light=CreateLight() caixa = LoadMesh("midia\supplies.x") caixa2 = LoadMesh("midia\supplies.x", caixa) MoveEntity caixa2, 30,0,0 While Not KeyHit(1) If KeyHit(57) Then ob = Not(ob) If ob If KeyDown(200) Then TranslateEntity caixa, 0, .1, 0

Clonar modelos Sabemos que a velocidade de acesso a dados no disco rgido do computador bem lenta se comparada capacidade geral de processamento da mquina. Se tivermos uma situao onde temos que usar vrias instncias de um mesmo objeto podemos clonar um objeto em vez de carregar vrias cpias dele com o LoadMesh, pois isso seria um pouco demorado. Para clonar um objeto usamos o comando CopyEntity. A tendncia normal de um iniciante em Blitz3D tentar usar um simples comando de atribuio para fazer uma cpia, como na linha abaixo:
Objeto1 = LoadMesh(midia\caixa.x) Objeto2 = Objeto1

Esse exemplo est incorreto, pois quanto o Blitz3D carrega um objeto, ou uma imagem, ele cria um ponteiro para o mesmo. Assim, a varivel Objeto1 no possui um modelo 3d, mas s a referncia ao endereo de memria do modelo. Dessa forma, quando fazemos a atribuio para a segunda varivel estamos na verdade passando o endereo do primeiro objeto para ele e todos os comandos que aplicarmos a esse segundo objeto vo valer para o objeto original, que continuar a ser o nico a existir. Assim o que fizemos na

verdade criar uma nova varivel para um mesmo objeto. Veja abaixo como fazer uma clonagem de maneira correta com o uso de CopyEntity. Exemplo 29
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,0,-80 light=CreateLight() caixa = LoadMesh("midia\supplies.x") caixa2 = CopyMesh(caixa) MoveEntity caixa2, 30,0,0 RenderWorld Flip WaitKey End

HideEntity caixa Text 30, 25, "OBJETO -> HIDE" EndIf Text 300, 0, "SPACE => HIDE/SHOW" Text 30, 40, "Triangulos Renderizados: " + TrisRendered() Flip Wend End

Veja que usamos os comando para alternar os modos Hide e Show. Tambm colocamos o comando TrisRendered(), que retorna o nmero de tringulos que esto sendo renderizados, para mostrar que em modo Hide no existe esforo de processamento. Objetos em Alpha O Blitz3D possui o poder de torna um objeto parcial ou totalmente transparente. Esse ajuste na camada alfa de um objeto muito til para vrios efeitos especiais. Podemos simular materiais translcidos como lquidos, vidros, plsticos, gua, etc. Outra aplicao importante dessa funcionalidade criar objetos auxiliares para a fsica e para verificar colises de forma mais precisa. Criamos os objetos auxiliares e deixarmos eles totalmente transparentes, assim podemos verificar colises com eles e ningum os ver. Um exemplo para esse tipo de aplicao criar limitadores de movimento, no caso de o personagem no poder passar de um ponto do cenrio, colocamos um plane totalmente transparente. Outro exemplo de uso para a fsica de carros onde colocamos uma esfera em cada ponto onde esto as rodas para verificarmos a altura exata do terreno naquele local e podermos ajustar a inclinao do carro de forma correta. Vamos a um exemplo do uso de canal alfa em objetos 3d.

Esse comando tambm suporta a criao de hierarquia Ocultando Objetos Existem jogos com cenrios muito grandes e ordenar que o Blitz3D faa o processamento grfico de todos eles exigiria um demanda muito grande de hardware. Existem duas solues possveis para isso, a primeira delas ir carregando objetos em tempo de execuo, o que poderia causar retardamentos, os famosos Lags, o outra soluo ocultar os objetos que no esto sendo usados, objetos que esto distantes do foco da cmera. Para usar essa tcnica usamos os comandos HideEntity e ShowEntity. O primeiro comando responsvel por esconder um objeto, isso , dizer para a engine que esse objeto no deve ter sua imagem processada e nem verificar colises para ele. J o comando ShowEntity reativa o processamento de um objeto que foi omitido pelo comando HideEntity. O exemplo abaixo faz uso dos dois comandos Exemplo 30
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,0,-30 light=CreateLight() caixa = LoadMesh("midia\supplies.x") SHW = 1 While Not KeyHit(1) If KeyHit(57) Then SHW = Not(SHW) RenderWorld If SHW ShowEntity caixa Text 30, 25, "OBJETO -> SHOW" Else

light=CreateLight() caixa = LoadMesh("midia\supplies.x") caixa2 = CopyMesh(caixa) PositionEntity caixa, 15, 0, 0 pincel = CreateBrush() While Not KeyHit(1) If KeyHit(57) r = Rnd(255) g = Rnd(255) b = Rnd(255) BrushColor pincel, r, g, b PaintMesh caixa, pincel EntityColor caixa2, r, g, b EndIf RenderWorld Flip Wend End O comando EntityColor recebe 4

Exemplo 31
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,0,-20 light=CreateLight() caixa = LoadMesh("midia\supplies.x") caixa2 = CopyMesh(caixa) PositionEntity caixa2, 10, 0, 5 While Not KeyHit(1) x# = x# + 0.002 If x# > 1 Then x# = 0 EntityAlpha caixa, x# RenderWorld Text 10,10, "VALOR ALPHA: " + X# Flip Wend End O comando EntityAlpha recebe dois

parmetros: o objeto a ser colorizado, a saturao red, a saturao green e a saturao blue (vermelho, verde e azul).
EntityColor caixa2, r, g, b

parmetros: o objeto a ser aplicado o efeito e a intensidade do canal alfa. A intensidade um valor de 0 at 1. O valor 0 significa totalmente transparente e o valor 1 totalmente opaco. Os valores intermedirios correspondem a transparncias intermedirias. Adicionar Cor O comando EntityColor capaz de colorir um modelo 3d. Esse comando diferente do comando PaintMesh, que uma colorao exclusiva. Quando aplicamos o comando EntityColor sobre um objeto que possui uma textura, essa cor adicionada textura do objeto, fazendo um Blend, enquanto que o comando PaintMesh remove a textura dele. Exemplo 32
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,0,-30

MODELOS ANIMADOS O Blitz3D possui suporte a 4 tipos de modelos animados: modelos .3ds que so nativos do 3ds Max, modelos .X que so nativos Microsoft Directx, modelos .b3d que so proprietrios do Blitz3D e modelos .md2 que so nativos da engine Quake2. Os modelos .md2 vo ser tratados em um captulo a parte, pois como eles possuem uma estrutura diferente, possuem comandos diferentes tambm. Os demais modelos possuem a mesma estrutura lgica e so controlados pelos mesmos comandos. Em nosso primeiro exemplo de modelos 3d animados, vamos carregar e animar um modelo do formato Directx criado pelo prprio Mark Sibly que vem como exemplo no Blitz3d. Exemplo 33
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,20,-50 light=CreateLight() robo = LoadAnimMesh("midia\robo1.x") Animate robo While Not KeyHit(1) UpdateWorld RenderWorld Flip Wend End

A primeira novidade que temos nesse programa o comando para carregar o modelo animado.
robo = LoadAnimMesh("midia\robo1.x")

Veja que agora o comando LoadAnimMesh, isso carregar um modelo animado. Alm da localizao do arquivo, esse comando tambm pode aceitar uma entidade pai para compor uma hierarquia, como seu segundo argumento. O segundo comando que estamos vendo pela primeira vez aqui o comando de animao de modelos 3d.
Animate robo

Exemplo 34
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,20,-70 light=CreateLight() robo = LoadAnimMesh("midia\robo2.3ds") Animate robo While Not KeyHit(1) UpdateWorld RenderWorld Flip Wend End

Veja que passamos apenas um argumento para o comando Animate: a entidade a ser animada. Mas esse comando muito mais complexo. Veja abaixo sua assinatura completa: Animate objeto, modo, velocidade, seqncia, transio Como j sabemos, o objeto um modelo animado que j carregamos. O modo o tipo de animao que iremos aplicar ao modelo. Esse parmetro opcional. Os tipos so: 0 parado 1 animao em loop (o padro, animao continua sem parar) 2 animao ping-pong (animao continua mas em forma de vai e volta) 3 nica (anima s uma vez, do frame 0 at o final e para) O nosso terceiro parmetro velocidade. Com esse parmetro nos definimos com qual velocidade a animao ir rodar. Esse parmetro tambm opcional. O parmetro seguinte o seqncia. Esse parmetro depende de termos previamente carregado uma animao pelo mtodo ExtractAnimSeq. Quando no usamos esse comando toda a animao carregada em apenas uma seqncia, a seqncia 0, pelo mtodo LoadAnimMesh. Por fim, o parmetro transio define como se dar a transio do ultimo frame da animao para o primeiro. O ultimo comando que aparece pela primeira vez nesse programa o de atualizao do cenrio 3d.
UpdateWorld

Veja agora um exemplo com modelo .b3d. Esse modelo vem junto com o programa CharacterFX, um software para animao de personagens de baixo custo que exporta para os modelos .b3d, .x, .3ds, .md2, .n, .obj e milkshape3d.txt.

Exemplo 35
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,20,-100 light=CreateLight() yago = LoadAnimMesh("midia\yago.b3d") RotateEntity yago, 0, 150, 0 Animate yago While Not KeyHit(1) UpdateWorld RenderWorld Flip Wend End

Esse comando muito importante, sem ele a animao no acontece e as colises no podem ser verificadas, pois ele que atualiza essas funcionalidades. Como dissemos anteriormente, os mesmos comando so validos para os modelos .3ds, .x e .b3d. Veja a seguir o mesmo programa agora carregando um modelo do formato .3ds.

Tipos de Animao Voc pode configurar o comando Animate para 4 tipos de estados de animao: parado, loop, ping-pong e nica. O programa de exemplo abaixo mostra como funciona e como configuramos isso. Use a barra de

espao para mudar os tipos de estado de animao. Exemplo 36


Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,20,-70 light=CreateLight() robo = LoadAnimMesh("midia\robo2.3ds") tipo = 0 While Not KeyHit(1) If KeyHit(57) tipo = tipo + 1 If tipo = 4 Then tipo = 0 Animate robo, tipo EndIf UpdateWorld RenderWorld Text 250,10, "TECLE SPACE PARA MUDAR O TIPO DE ANIMAO" If tipo = 0 Then Text 10,25, "TIPO ATUAL: PARADO" If tipo = 1 Then Text 10,25, "TIPO ATUAL: LOOP" If tipo = 2 Then Text 10,25, "TIPO ATUAL: PING-PONG" If tipo = 3 Then Text 10,25, "TIPO ATUAL: UNICA" Flip Wend End

End

Mudando velocidade Como sabemos, o terceiro parmetro do comando Animate a velocidade da animao. Nosso prximo exemplo mostra como aplicar essa configurao. Exemplo 37
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,20,-70 light=CreateLight() robo = LoadAnimMesh("midia\robo2.3ds") velox# = 0.1 Animate robo,1, velox# While Not KeyHit(1) If KeyDown(200) velox# = velox# + 0.02 Animate robo,1, velox# EndIf If KeyDown(208) velox# = velox# - 0.02 Animate robo,1, velox# EndIf UpdateWorld RenderWorld Text 150,10, "SETA ACIMA -> aumenta velocidade; SETA ABAIXO -> diminui Text 10,25, Velocidade atual: + velox# Flip Wend

Carregar seqncias de animaes Algo que facilita muito na hora de criar um jogo dividir as animaes em unidades lgicas separadas. Assim, podemos at criar uma varivel para cada animao, ficando mais obvio o que cada coisa faz, pois afinal Animate robo, 1, 1, corre bem mais fcil de entender e de fazer que que ter que verificar qual o frame atual e se o frame for o frame final, reiniciar o frame da animao, etc... Como voc j percebeu, sem a extrao de animao a coisa fica bem mais complicada. Ento vamos a um exemplo prtico. A primeira coisa a saber : quais so as animaes disponveis no modelo. O nosso amigo ninja que vamos usar, que um modelo que vem junto com o Character FX, tem a seguinte especificao: 1-14 Walk 15-30 Stealth Walk 32-44 Punch and swipe sword 45-59 Swipe and spin sword 60-68 Overhead twohanded downswipe 69-72 Up to block position 73-83 Forward kick 84-93 Pick up from floor 94-102 Jump 103-111 Jump without height 112-125 High jump to Sword Kill 126-133 Side Kick 134-145 Spinning Sword attack 146-158 Backflip 159-165 Climb wall 166-173 Death 1 - Fall back onto ground 174-182 Death 2 - Fall forward onto ground 184-205 Idle 1 - Breathe heavily 206-250 Idle 2 251-300 Idle 3 O nosso primeiro programa vai fazer uma demonstrao de todos os elementos da animao. Exemplo 38
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,5,-10 light=CreateLight() ninja = LoadAnimMesh("midia\ninja.b3d") RotateEntity ninja, 0, 150, 0 Animate ninja,1, .1 While Not KeyHit(1) UpdateWorld RenderWorld Text 10,10, "FRAME: " + AnimTime(ninja)

Flip Wend End

Veja que usamos o comando AnimTime() que retorna a animao atual de um modelo animado para verificar em qual parte da animao estamos. Para nosso exemplo prtico no vamos usar todas as seqncias apresentadas, mas s quelas que nos interessam: 1-14 Walk (andar) 60-68 Overhead twohanded downswipe (golpear) 126-133 Side Kick (chutar) 146-158 Backflip (saltar) Vamos ao cdigo! Exemplo 39
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,5,-15 light=CreateLight() ninja = LoadAnimMesh("midia\ninja.b3d") andar = ExtractAnimSeq( ninja,1,14 ) golpear = ExtractAnimSeq( ninja,60,68 ) chutar = ExtractAnimSeq( ninja,126,133 ) saltar = ExtractAnimSeq( ninja,146,158 ) RotateEntity ninja, 0, 200, 0 Animate ninja, 1, .2, andar While Not KeyHit(1) If KeyHit(57) Then Animate ninja, 1, .2, saltar If KeyHit(44) Then Animate ninja, 1, .2, golpear If KeyHit(45) Then Animate ninja, 1, .2, chutar UpdateWorld RenderWorld Text 10,10, "SPACE-> Saltar; Z -> Golpear; X -> Chutar" Flip Wend End

O que fizemos a seguir foi indexar cada animao ao apertar de uma tecla. Assim configuramos o comportamento do modelo animado com nossas teclas configuradas para o controle.
If KeyHit(57) Then Animate ninja, 1, .2, saltar If KeyHit(44) Then Animate ninja, 1, .2, golpear If KeyHit(45) Then Animate ninja, 1, .2, chutar

Como voc pode perceber, est faltando algo ai, afinal, quando apertamos uma tecla, como a chutar, por exemplo, ele comea a chutar sem parar. O ideal que ele d apenas um chute e volte para seu estado inicial. Assim, cada vez que apertarmos uma tecla de comportamento ele deve executar a ao apenas enquanto a tecla estiver pressionada. No fizemos isso por enquanto para no complicar muito. Vamos implementar passo o passo. O nosso prximo passo fazer isso, fazer com que o personagem volte a seu estado de animao primitivo. Para que o personagem volte a sua animao primitiva teremos que fazer a verificao se a animao chegou ao seu final. Se ela chegou ao fim, ento ordenamos que rode a animao principal. Para fazer isso vamos usar o comando AnimTime(), que nos informa qual o frame atual de uma animao. Veja o exemplo prtico Exemplo 40
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,5,-15 light=CreateLight() ninja = LoadAnimMesh("midia\ninja.b3d") RotateEntity ninja, 0, 200, 0 parado = ExtractAnimSeq( ninja,5,5) golpear = ExtractAnimSeq( ninja,60,68 ) chutar = ExtractAnimSeq( ninja,126,133 ) saltar = ExtractAnimSeq( ninja,146,158 ) Animate ninja, 1, .2, parado anima = parado While Not KeyHit(1) If KeyHit(57) Animate ninja, 1, .2, saltar anima = saltar EndIf If KeyHit(44) Animate ninja, 1, .2, golpear anima = golpear EndIf If KeyHit(45) Animate ninja, 1, .2, chutar anima = chutar EndIf

A primeira coisa que fizemos foi extrair as animaes e colocar em variveis com nomes que indiquem o seu contedo:
andar = ExtractAnimSeq( ninja,1,14 ) golpear = ExtractAnimSeq( ninja,60,68 ) chutar = ExtractAnimSeq( ninja,126,133 ) saltar = ExtractAnimSeq( ninja,146,158 )

Como o nosso modelo tem um documento de especificao isso foi fcil. Caso o modelo que voc use no o possua, voc ter que rodar a animao toda em uma velocidade bem baixa para verificar quais frames compe qual animao. Vamos iniciar a aplicao com o modelo andando mesmo:
Animate ninja, 1, .2, andar

frame = AnimTime(ninja) If anima = golpear And (frame > 7) Animate ninja, 1, .2, parado anima = parado EndIf If anima = chutar And (frame > 6) Animate ninja, 1, .2, parado anima = parado EndIf If anima = saltar And (frame > 11) Animate ninja, 1, .2, parado anima = parado EndIf UpdateWorld RenderWorld Text 10,10, "SPACE-> Saltar; Z -> Golpear; X -> Chutar" Flip Wend End

estava no alto e de ponta cabeo e de repente aparece de p saltando de novo. Para resolver isso muito simples. Como j temos uma varivel informando qual a animao atual, s vamos permitir uma nova animao quando a animao atual for a inicial, isso , estiver parado. Exemplo 41
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,5,-15 light=CreateLight() ninja = LoadAnimMesh("midia\ninja.b3d") RotateEntity ninja, 0, 200, 0 parado = ExtractAnimSeq( ninja,5,5) golpear = ExtractAnimSeq( ninja,60,68 ) chutar = ExtractAnimSeq( ninja,126,133 ) saltar = ExtractAnimSeq( ninja,146,158 ) Animate ninja, 1, .2, parado anima = parado While Not KeyHit(1) If KeyHit(57) And Anima = parado Animate ninja, 1, .2, saltar anima = saltar EndIf If KeyHit(44) And Anima = parado Animate ninja, 1, .2, golpear anima = golpear EndIf If KeyHit(45) And Anima = parado Animate ninja, 1, .2, chutar anima = chutar EndIf frame = AnimTime(ninja) If anima = golpear And (frame > 7) Animate ninja, 1, .2, parado anima = parado EndIf If anima = chutar And (frame > 6) Animate ninja, 1, .2, parado anima = parado EndIf If anima = saltar And (frame > 11) Animate ninja, 1, .2, parado anima = parado EndIf UpdateWorld RenderWorld Text 10,10, "SPACE-> Saltar; Z -> Golpear; X -> Chutar" Flip Wend End

Dessa vez iniciamos com o personagem parado, para isso criamos uma animao de parado com apenas um frame.
parado = ExtractAnimSeq( ninja,5,5)

Tambm criamos uma varivel para informa qual a animao em curso. Isso vai facilitar na hora de verificar o frame atual.
anima = parado

Agora, quando pressionamos uma tecla de animao, alm de acionar a animao correspondente, tambm configuramos a varivel de informao do tipo de animao.
If KeyHit(57) Animate ninja, 1, .2, saltar anima = saltar EndIf

Por fim a verificao dos frames.


frame = AnimTime(ninja) If anima = golpear And (frame > 7) Animate ninja, 1, .2, parado anima = parado EndIf

Veja que colocamos o frame atual em uma varivel Frame o passo seguinte verificar qual a animao atual If anima = golpear e como a animao golpear tem 8 frames, verificamos se ela chegou a seu ltimo frame, o frame 8 isso , frame > 7. Se essas duas condies forem verdadeiras, ento colocamos a animao em seu estado inicial Animate ninja, 1, .2, parado e configuramos a varivel de informao anima=parado. Veja que fizemos um algoritmo desse para cada tipo de animao. Se voc ficou bem atento j deve ter percebido que ainda falta uma coisa. Quando apertamos uma tecla de animao mais de uma vez o modelo para a animao em curso e reinicia a partir do frame inicial. Isso pssimo, pois, por exemplo, no salto, ele

Veja onde resolvemos o problema:


If KeyHit(57) And Anima = parado Adicionamos mais uma condio And Anima = parado para acionar uma animao. Agora

a animao atual dever ser o estado parado para que seja disparada uma nova animao. Em um jogo voc dever verificar em que estados seu personagem poder iniciar uma nova animao. Os mais comuns

so a partir dos estados: parado, andando e correndo. Estados como atacando, atirando, saltando jamais devem ser estados iniciais a parir dos quais se inicia uma nova animao. Por hora s podemos avanar at aqui em modelos animados. Depois que fizermos um estudo sobre cmeras e cenrios passaremos a exemplos prticos com modelos animados, onde iremos entrar em animaes, algoritmos e eventos. Da ns veremos como colocar isso em prtica em um jogo. MODELOS MD2 Os modelos .md2 tem uma estrutura diferente dos demais modelos 3d, por isso foram criados comandos prprios para ele. O Blitz3D oferece 5 comandos para controlar os modelos .md2. Veja-os abaixo: LoadMD2 (carrega um modelo 3d do tipo .md2) AnimateMD2 (anima um modelo .md2) MD2AnimTime (retorna o frame atual da animao) MD2AnimLength (retorna o tamanho da animao) MD2Animating (retorna 1 se o modelo est animado e 0 se no) Os comandos MD2AnimTime, MD2AnimLength e MD2Animating tem a assinatura muito simples, pois s aceitam um parmetro: o modelo md2 carregado. O comando LoadMd2 alm de aceitar o arquivo que possui o modelo 3d do tipo md2 tambm aceita como parmetro um modelo para compor uma hierarquia. O comando AnimateMD2 mais complexo. Ele aceita 6 parmetros. Veja sua assinatura:
AnimateMD2 modelo, modo, velocidade, primeiro frame, ultimo frame, transio.

livre e pode ser encontrado junto com a Irrlicht Engine. Exemplo 42


Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera, 0,10,-50 light=CreateLight() RotateEntity light,90,0,0 sid=LoadMD2( "midia/sydney.md2" ) tex=LoadTexture( "midia/sydney.bmp" ) EntityTexture sid, tex RotateEntity sid,0,150,0 AnimateMD2 sid,1,0.1,0,198 While Not KeyDown( 1 ) UpdateWorld RenderWorld Text 10,10, "TAMANHO ANIMAO: " + MD2AnimLength(sid) Text 10,25, "FRAME ATUAL: " + MD2AnimTime (sid) Text 10,40, "ESTADO DA ANIM: " + MD2Animating(sid) Flip Wend End

8. JOGOS 3D Parte II Vamos iniciar a segunda parte de programao de jogos 3d. O mundo 3d realmente repleto de entidades e propriedades e vamos dar um passo a mais adentro desse universo maravilhoso. Nesta seo vamos estudar os demais elementos que compe um jogo 3d: cenrio, cmeras, iluminao, sprites, fsica e tambm vamos dar exemplos prticos de como implementar funcionalidades essenciais de um jogo. Colises A deteco de colises a alma de um jogo. Sem essa funcionalidade fsica tudo se daria em um mundo neutro. por meio dela que pegamos itens, atiramos, interagimos com o cenrio, etc. Vamos primeiro estudar o sistema de colises automticas do Blitz3D. Esse sistema de fsica disponvel na engine disponibiliza 3 tipos de verificaes de colises: 1. Esfera com esfera 2. Esfera com polgono 3. Esfera com caixa Alm de verificar colises, o Blitz3D tambm produz resultados fsicos automticos dessas colises. Podemos escolher qual ser o resultado desse evento. 1. O objeto para

Apenas o primeiro parmetro, o modelo a ser animado, obrigatrio, sendo os demais opcionais. Veja que ele possui uma diferena em relao ao comando para animar os outros tipos de modelos. Ele no aceita uma seqncia de animao, mas sim frame inicial e frame final. Uma peculiariedade de um modelo .md2 que sua texturizao deve ser feita manualmente no Blitz3D. Vamos dar um exemplo de manipulao de modelos md2 que contenha todos os comando. Vamos usar o modelo Sydney que

2. O objeto desliza 3. O objeto desliza em relao ao ngulo. Para criar um perfeito sistema de colises necessrio um pouco de cuidado para no criar comandos desnecessrios e nem sobrecarregar o sistema com excesso de verificaes. O ideal verificar colises por meio de grupos de objetos, isso , criamos um grupo de objetos que possuem s mesmas caractersticas fsica e verificamos as colises em grupo. Veja as etapas necessrias para isso: 1. passo: criar grupos de objetos (parede, rvore, etc) 2. passo: dizer a qual grupo cada objeto pertence. 3. passo: habilitar as colises. 4. passo: verificar as colises. 5. passo: ativar o updateworld. 1 PASSO: Criar Grupos de Objetos Imagine que no seu jogo voc tenha umas 50 entidades do tipo paredes e muros. Paredes e muros tm o mesmo comportamento fsico, quando um objeto os atinge, ele no atravessa, mas tende a deslizar. Como voc possui 50 objetos distintos e tem que fazer verificao de colises para os 50, ento teramos 50 linhas para configurar as colises? A resposta : s se voc quiser! Voc pode criar um grupo de objetos e dizer que os objetos pertencem aquele grupo especfico. Ai em vez de ter 50 linhas para configurar as colises e mais cinqenta para verificar, voc s vai ter 2 linhas. Isso que estamos falando no um comando de colises, mas uma tcnica para organizar o cdigo. Vamos fazer isso por meio de uma constante. Vamos criar uma constante que defina um grupo de objetos Const OB_PAREDE = 1 Veja que o que fizemos foi criar uma constante e atribuir a ela um nmero. que os tipos de objetos para colises no Blitz3D no numerados de 0 a 999. 2 PASSO: Determinar a qual tipo um objeto pertence Todo o objeto que precisa ter verificao de colises precisa pertencer a um tipo, pois a verificao de colises feita por tipos (nmeros de 0-999). No nosso caso, estamos criando grupos de tipos e definimos anteriormente que o grupo OB_PAREDE do tipo 1. O que temos que fazer agora

dizer que nossa parede pertence a esse grupo de objetos, isso , ela do tipo 1. EntityType parede1, OB_PAREDE EntityType parede2, OB_PAREDE . . . EntityType HEROY, 999 3 PASSO: Habilitar colises Depois de configuras todos dos tipos de objetos, o prximo passo dizer quais so as colises que o Blitz3D dever verificar. Como ns criamos grupos isso ficar mais fcil, pois devemos dizer apenas que o personagem principal vai colidir com aquele grupo. Assim usamos esse comando apenas uma vez para cada grupo de objetos. Collisions 999, OB_PAREDE, 3, 1 Esse comando j um tanto quanto mais complexo e merece uma explicao mais detalhada. O primeiro parmetro o tipo do objeto principal, o que dever colidir com os outros objetos. Normalmente o personagem principal do jogo ou outro objeto que possua comportamento ativo. Collisions TIPO_DO_OBJETO_PRINCIPAL, OB_PAREDE, 3, 1 O segundo parmetro se refere ao objeto (ou aos objetos secundrios) que recebem a ao. No nosso caso o cenrio, as paredes. Collisions 999, OB_PAREDE, 3, 1 O terceiro parmetro se refere ao tipo de verificao de coliso. Lembre-se da tabelinha: 1 Esfera com esfera 2 Esfera com polgono 3 Esfera com caixa assim o comando: Collisions 999, OB_PAREDE, 3, 1 Est criando uma verificao de coliso do tipo Esfera com Caixa, pois o tipo 3. As caixas sero os muros e paredes e a esfera ser o Heroy. Veja que sempre o primeiro objeto, o principal uma esfera nesse sistema. 4 PASSO: Verificar Colises Esse quarto passo nem sempre necessrio, pois a maior parte das colises so apenas para criar efeitos de fsica, como impedir que um personagem atravesse uma parede, ou que quando saltemos, ao cair no atravessemos o cho, etc.

Mas em casos como verificao de colises com tiros, com itens, etc, devemos criar um comando especial quando houver uma coliso. Se nos chocamos com uma bala perdida, perdemos vida, se tocarmos um item, ganhamos novos status, etc. Para isso, o Blitz3D disponibiliza o comandoEntityCollided, que verifica se um objeto colidiu com outro. If EntityCollided(Heroy, OB_PAREDE) Then Print PARE Perceba que esse comando no tipo, tipo. Ele recebe os parmetros objeto, tipo, isso verifica se uma Entidade (Heroy) est colidindo com um grupo de objetos. Portanto, no seria possvel fazer uma verificao do igual a EntityCollided(999,1), mas poderia ser EntityCollided(Heroy,1) pois sua assinatura : EntityCollided(Objeto3d, tipo) Se precisarmos descobrir qual o objeto do grupo que colidiu, esse comando retorna a referncia desse objeto, portanto s precisamos fazer uma atribuio a uma varivel. Objeto = EntityCollided(Objeto3d, tipo) Vamos a parte prtica agora! Exemplo 1
Graphics3D 800,600 SetBuffer BackBuffer() Const OB_CONE=1 Const OB_BOLA=2 camera=CreateCamera() PositionEntity camera,0,0,-5 light = CreateLight() cone=CreateCone() PositionEntity cone,-5,0,5 EntityColor cone,0,200,0 EntityType cone,OB_CONE bola=CreateSphere(12) PositionEntity bola,5,0,5 EntityColor bola,200,0,0 EntityType bola, OB_BOLA Collisions OB_BOLA,OB_CONE,3,1 While Not KeyHit(1) MoveEntity bola,-0.02,0,0 UpdateWorld RenderWorld If EntityCollided(bola,OB_CONE) Then Text 380,50,"COLIDE" Flip Wend End

Const OB_BOLA=2

Veja que criamos um grupo para o objeto do tipo cone e um para a bola. Eles sero de tipos diferentes pelo fato de possuirem comportamentos diferentes. O passo seguinte dizer a qual grupo cada objeto pertence.
EntityType cone,OB_CONE

Logo aps o objeto ser criado, definimos a que grupo de entidades fsicas de colises ele pertence. Veja que o objeto cone pertence ao grupo OB_CONE.
EntityType bola, OB_BOLA

O objeto bola pertence ao grupo OB_BOLA. Agora que j criamos os objetos e configuramos os seus grupos, isso , declaramos a que grupo de objetos fsicos eles pertencem, o passo seguinte Ligar as colises.
Collisions OB_BOLA,OB_CONE,3,1

Veja que estamos ativando colises entre os tipos OB_BOLA e OB_CONE, isso , estamos dizendo ao Blitz3D quero que voc crie um sistema de colises entre os objetos do tipo OB_BOLAe OB_CONE. Veja que estamos dizendo ao Blitz para criar esse sistema de colises como Esfera-Caixa, afinal ativamos a flag 3 para tipo de colises e informamos tambm que desejamos que os objetos fiquem parados quando colidirem, pois acionamos a flag 1 para o comportamento fsico. Veja que esse comando fica fora do loop, pois ele s precisa ser informado uma nica vez. Por fim, quando os objetos colidirem iremos exibir uma mensagem de texto:
If EntityCollided(bola,OB_CONE) Then Text 380,50,"COLIDE"

Repare que o primeiro parmetro um modelo 3d e o segundo um tipo de objeto. Isso , verificamos se o objeto bola est colidindo com algum objeto do tipo cone. Como voc pode ter percebido, a coliso no muito precisa, afinal temos um cone como objeto e verificamos colises com cubo. Isso gera uma diferena e acaba detectando a coliso mesmo antes de ela ocorre. Para resolver esse problema, vamos usar uma coliso do tipo 2, isso , EsferaPolgono. Exemplo 2
Graphics3D 800,600 SetBuffer BackBuffer() Const OB_CONE=1 Const OB_BOLA=2

A primeira coisa que fizemos foi criar os grupos de objetos. Embora nesse exemplo tenhamos apenas um objeto para cada tipo, fizemos por efeito didtico.
Const OB_CONE=1

camera=CreateCamera() PositionEntity camera,0,0,-5 light = CreateLight() cone=CreateCone() PositionEntity cone,-5,0,5 EntityColor cone,0,200,0 EntityType cone,OB_CONE bola=CreateSphere(12) PositionEntity bola,5,0,5 EntityColor bola,200,0,0 EntityType bola, OB_BOLA Collisions OB_BOLA,OB_CONE,2,1 While Not KeyHit(1) MoveEntity bola,-0.02,0,0 UpdateWorld RenderWorld If EntityCollided(bola,OB_CONE) Then Text 380,50,"COLIDE" Flip Wend End

Veja que precisamos mudar apenas um dado em uma linha:


Collisions OB_BOLA,OB_CONE,2,1

Trocamos o parmetro 3 (esfera-caixa) para a flag 2(esfera-polgono), e agora temos um sistema de colises mais preciso. Embora a coliso esteja precisa, a nossa bola simplesmente para ao se chocar com o cone. Isso no ocorre num mundo real. Vamos alterar o parmetro de resultado fsico da coliso para deslizar, a flag 2. Exemplo 3
Graphics3D 800,600 SetBuffer BackBuffer() Const OB_CONE=1 Const OB_BOLA=2 camera=CreateCamera() PositionEntity camera,0,0,-5 light = CreateLight() cone=CreateCone() PositionEntity cone,-5,0,5 EntityColor cone,0,200,0 EntityType cone,OB_CONE bola=CreateSphere(12) PositionEntity bola,5,0,5 EntityColor bola,200,0,0 EntityType bola, OB_BOLA Collisions OB_BOLA,OB_CONE,2,2 While Not KeyHit(1) MoveEntity bola,-0.02,0,0 UpdateWorld RenderWorld If EntityCollided(bola,OB_CONE) Then Text 380,50,"COLIDE" Flip Wend End

Quando ligamos as colises para um tipo de objeto, o Blitz3D verifica qual o tipo de coliso que aquele objeto possui e se for um objeto do tipo Esfera ou Caixa o Blitz cria uma esfera ou uma caixa de coliso para ele. Mas infelizmente nem sempre ele faz isso com o tamanho correto, pois por padro ele cria uma caixa de 2x2x2 e uma esfera de raio 1. E, as vezes, isso pequeno demais ou grande demais para o objeto que estamos trabalhando. Podemos configurar o tamanho da entidade de coliso por meio dos comandos EntityRadius (para colises por esferas) e EntityBox (para colises por caixas). Para manipular o comando EntityBox devemos passar os parmetros do objeto a ter sua caixa de colises alterada, as posies x, y e z novas para a caixa e as 3 novas dimenses, largura, altura e profundidade. O comando EntityRadius necessita apenas do parmetro co objeto a ser configurado e o novo raio da esfera. No exemplo abaixo diminumos o raio original da esfera. Confira o resultado. Exemplo 4
Graphics3D 800,600 SetBuffer BackBuffer() Const OB_CONE=1 Const OB_BOLA=2 camera=CreateCamera() PositionEntity camera,0,0,-5 light = CreateLight() cone=CreateCone() PositionEntity cone,-5,0,5 EntityColor cone,0,200,0 EntityType cone,OB_CONE bola=CreateSphere(12) PositionEntity bola,5,0,5 EntityColor bola,200,0,0 EntityType bola, OB_BOLA EntityRadius bola, .1 Collisions OB_BOLA,OB_CONE,3,1 While Not KeyHit(1) MoveEntity bola,-0.02,0,0 UpdateWorld RenderWorld If EntityCollided(bola,OB_CONE) Then Text 380,50,"COLIDE" Flip Wend End

Novamente alteramos apenas uma flag em uma linha do cdigo


Collisions OB_BOLA,OB_CONE,2,2

Cenrios Existem duas tcnicas predominantes na criao de cenrios: o uso de modelos 3d e o uso de terrenos. O mais comum usar

Manipulando Entidade de Coliso

apenas modelos 3d ou ento a combinao das duas tcnicas. Os modelos 3d so modelos comuns, s que nesse caso so maiores que simples objetos e normalmente no possuem animaes. Podem ser criados em programas prprios de modelagem como 3ds Max, Maya, Anim8tor ou Blender, ou ento em programas prprios para a criao de cenrios como o Cshop. Os terrenos so na verdade uma imagem constituda por tons de cinza onde cada saturao de cor representa uma altitude do relevo. A menor saturao de cor (0,0,0), que o preto absoluto, representa o ponto mais baixo do terreno e a saturao mxima (255,255,255), branco absoluto, representa o ponto mais alto do cenrio. As saturaes intermedirias representam alturas intermedirias. Dessa forma, a imagem vai criar um mapa fsico de relevo que poder ser texturizado para criar um alto nvel de realismo. Os terrenos podem ser criados em qualquer programa de edio de imagem que tenha suporte a ferramentas de pincel com controle de saturao (canal alpha). Existem vrios programas 3d que tambm criam terrenos a partir de modelos 3d. Esses programas so a melhor maneira de lidar com essa tcnica, pois temos uma visualizao de como ficar o resultado. Cenrios com modelos 3d Se formos criar todo o cenrio a partir de modelos 3d no seria uma boa prtica criar tudo em um nico modelo. O Blitz3D possui um sistema avanado de renderizao que s processa os modelos 3D que esto na frente da cmera e dentro da rea de viso estabelecida para essa. Se criarmos todo o cenrio em um nico objeto 3d ele inteiro vai ser processado o tempo todo, pois sempre haver uma parte dele na frente da cmera. Do contrrio, se o dividirmos em partes, s ser processada a parte do cenrio que estiver em nosso ngulo de viso. Voc pode definir a melhor estratgia para trabalhar com essa caracterstica da engine. As melhores opes so: carregar cada objeto individualmente ou dividir o cenrio em setores. No primeiro exemplo que vamos apresentar abaixo estamos usando essa tcnica, por isso vamos separar o cenrio em parte: base,

objetos, casas, etc e carrear tudo individualmente, embora isso seja um pouco trabalhoso, garante uma melhor performance em aplicaes grandes. Veja como ficou nosso cenrio base:

Exemplo 5
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,20,-120 light=CreateLight() RotateEntity light,90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) While Not KeyDown( 1 ) RenderWorld Flip Wend End

No exemplo a seguir, usamos o mesmo modelo 3d, mas como sabemos que ele possui exatamente 200x150, usamos essa medida para criar um cenrio maior por meio de cpias do primeiro. s copiar o modelo e colocar numa posio de deslocamento igual ao comprimento e/ou largura dele. Perceba que ele se encaixa com tal preciso que no sabemos onde est a emenda. Tambm estamos usando as teclas de setas para move no cenrio. Confira o resultado. Exemplo 6
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,20,-120 light=CreateLight() RotateEntity light,90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) cenario2 = CopyMesh(cenario) cenario3 = CopyMesh(cenario) cenario4 = CopyMesh(cenario) cenario5 = CopyMesh(cenario) cenario6 = CopyMesh(cenario) PositionEntity cenario2, -150,0,0 PositionEntity cenario3, 150,0,0 PositionEntity cenario4, -150,0,200 PositionEntity cenario5, 0,0,200 PositionEntity cenario6, 150,0,200 While Not KeyDown( 1 )

If KeyDown( 205 ) Then TurnEntity camera,0,-1, 0 If KeyDown( 203 ) Then TurnEntity camera,0, 1, 0 If KeyDown( 208 ) Then MoveEntity camera,0, 0,-1 If KeyDown( 200 ) Then MoveEntity camera,0, 0, 1 RenderWorld Text 10,10, "USE AS SETAS PARA ANDAR" Flip Wend End

Veja que colocamos os novos elementos do cenrio em posies mltiplas de x=150 ou z=200, pois assim eles se encaixam perfeitamente, pois essas so as dimenses do modelo 3d.
PositionEntity PositionEntity PositionEntity PositionEntity PositionEntity cenario2, cenario3, cenario4, cenario5, cenario6, -150,0,0 150,0,0 -150,0,200 0,0,200 150,0,200

produzidos por ele como sprites, pois elas so muito complexas, de altssima qualidade grfica e apenas alguns modelos 3d dessas arvores j vo comprometer o desempenho. Uma soluo mais barata e leve pode ser programas como o TreeMagik que bem barato, criar infinidades de rvores e arbustos diferentes e produz LowPoly, isso , com poucos polgonos. As rvores que estamos usando aqui foram criadas no TreeMagik. Veja o resultado.

Usamos as teclas seta para a direita e seta para a esquerda para rotacionar a cmera no eixo y. Como voc se lembra, o eixo y aponta para cima, isso cria um efeito de rotao como se estivssemos virando nosso corpo para a direita ou para a esquerda.
If KeyDown( 205 ) Then TurnEntity camera,0,-1, 0 If KeyDown( 203 ) Then TurnEntity camera,0, 1, 0

Exemplo 7
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,20,-120 light=CreateLight() RotateEntity light,90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) cenario2 = CopyMesh(cenario) cenario3 = CopyMesh(cenario) cenario4 = CopyMesh(cenario) cenario5 = CopyMesh(cenario) cenario6 = CopyMesh(cenario) PositionEntity cenario2, -150,0,0 PositionEntity cenario3, 150,0,0 PositionEntity cenario4, -150,0,200 PositionEntity cenario5, 0,0,200 PositionEntity cenario6, 150,0,200 arvore1 = LoadMesh("midia/arv1.b3d") arvore2 = LoadMesh("midia/arv2.b3d") ScaleMesh arvore1, .05, .05, .05 ScaleMesh arvore2, .05, .05, .05 Dim arvoreA(10) Dim arvoreB(10) arvoreA(1) = arvore1 arvoreB(1) = arvore2 For x = 2 To 8 arvoreA(x) = CopyMesh(arvore1) arvoreB(x) = CopyMesh(arvore2) Next PositionEntity arvoreA(1), -13, 0, -50 PositionEntity arvoreA(2), 17, 0, -50 PositionEntity arvoreA(3), -13, 0, 50 PositionEntity arvoreA(4), 17, 0, 50 PositionEntity arvoreA(5), -13, 0, 150 PositionEntity arvoreA(6), 17, 0, 150 PositionEntity arvoreA(7), -13, 0, 250 PositionEntity arvoreA(8), 17, 0, 250 PositionEntity arvoreB(1), -50, 0, 15 PositionEntity arvoreB(2), -50, 0, 185

Usamos as setas para cima e para baixo para andarmos para frente e para traz. Para isso usamos o comando MoveEntity que, como voc recorda, ele faz um objeto se deslocar em eixos relativos a sua face. Frente e atrs em 3d o eixo Z. Portanto aumentar a posio no eixo z andar para frente e diminuir andar para traz. Como o comando MoveEntity baseado na face do objeto, quando rotacionamos a cmera, o movimento tambm passar a acompanhar a frente da cmera. Assim, sempre andar para frente da cmera ou para traz da mesma.
If KeyDown( 208 ) Then MoveEntity camera,0, 0,-1 If KeyDown( 200 ) Then MoveEntity camera,0, 0, 1

Adicionando algumas arvores Vamos agora adicionar alguns elementos paisagsticos ao cenrio para dar um efeito maior de realismo. Existem vrios programas que tornam a tarefa de cria modelos de rvores muito mais simples. O prprio 3ds Max tem uma funcionalidade incorporada, mas aconselho a usar os elementos

PositionEntity arvoreB(3),-100, 0, 15 PositionEntity arvoreB(4),-100, 0, 185 PositionEntity arvoreB(5), 50, 0, 15 PositionEntity arvoreB(6), 50, 0, 185 PositionEntity arvoreB(7), 100, 0, 15 PositionEntity arvoreB(8), 100, 0, 185 While Not KeyDown( 1 ) If KeyDown( 205 ) Then TurnEntity camera,0,-1,0 If KeyDown( 203 ) Then TurnEntity camera,0,1,0 If KeyDown( 208 ) Then MoveEntity camera,0,0,-1 If KeyDown( 200 ) Then MoveEntity camera,0,0,1 RenderWorld Text 10,10, "USE AS SETAS PARA ANDAR" Flip 0 Wend End

Agora vamos adicionar elementos mais humanos, um carro e duas casas. Veja abaixo como ficou nosso cenrio. Nada mal no mesmo?

Exemplo 8
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,20,-120 light=CreateLight() RotateEntity light,90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) cenario2 = CopyMesh(cenario) cenario3 = CopyMesh(cenario) cenario4 = CopyMesh(cenario) cenario5 = CopyMesh(cenario) cenario6 = CopyMesh(cenario) PositionEntity cenario2, -150,0,0 PositionEntity cenario3, 150,0,0 PositionEntity cenario4, -150,0,200 PositionEntity cenario5, 0,0,200 PositionEntity cenario6, 150,0,200 arvore1 = LoadMesh("midia/arv1.b3d") arvore2 = LoadMesh("midia/arv2.b3d") ScaleMesh arvore1, .05, .05, .05 ScaleMesh arvore2, .05, .05, .05 Dim arvoreA(10) Dim arvoreB(10) arvoreA(1) = arvore1 arvoreB(1) = arvore2 For x = 2 To 8

arvoreA(x) = CopyMesh(arvore1) arvoreB(x) = CopyMesh(arvore2) Next PositionEntity arvoreA(1), -13, 0, -50 PositionEntity arvoreA(2), 17, 0, -50 PositionEntity arvoreA(3), -13, 0, 50 PositionEntity arvoreA(4), 17, 0, 50 PositionEntity arvoreA(5), -13, 0, 150 PositionEntity arvoreA(6), 17, 0, 150 PositionEntity arvoreA(7), -13, 0, 250 PositionEntity arvoreA(8), 17, 0, 250 PositionEntity arvoreB(1), -50, 0, 15 PositionEntity arvoreB(2), -50, 0, 185 PositionEntity arvoreB(3),-100, 0, 15 PositionEntity arvoreB(4),-100, 0, 185 PositionEntity arvoreB(5), 50, 0, 15 PositionEntity arvoreB(6), 50, 0, 185 PositionEntity arvoreB(7), 100, 0, 15 PositionEntity arvoreB(8), 100, 0, 185 carro = LoadMesh("midia\jeep.3ds") ScaleEntity carro, .7, .7, .7 PositionEntity carro, 8, 0, -70 casa1 = LoadMesh("midia\casa.3ds") ScaleEntity casa1, 2.5, 2.5, 2.5 RotateEntity casa1, 0, 90, 0 PositionEntity casa1, -47, 1, -50 casa2 = LoadMesh("midia\casa2.3ds") ScaleEntity casa2, 2, 2, 2 RotateEntity casa2, 0, -90, 0 PositionEntity casa2, 51, 1, -50 While Not KeyDown( 1 ) If KeyDown( 205 ) Then TurnEntity camera,0,-1,0 If KeyDown( 203 ) Then TurnEntity camera,0,1,0 If KeyDown( 208 ) Then MoveEntity camera,0,0,-1 If KeyDown( 200 ) Then MoveEntity camera,0,0,1 RenderWorld Text 10,10, "USE AS SETAS PARA ANDAR" Flip Wend End

Cuidado com o uso de arvores. Por mais que elas seja LowPoly, a tendncia de usarmos diversas, assim ento, um cenrio mais realista dever ter vrias dezenas, sobrecarregando a engine. Se voc precisa ter muitas rvore em seu jogo ou aplicao de realidade virtual, faa a opo de usar rvores como sprites, vai ficar muito leve e a qualidade praticamente a mesma. Dessa forma voc poder usar centenas delas sem risco de sabotar a performance da mquina. Mais frente ns explicaremos como usar sprites. Terrenos

O Bitz3D possui uma tima interface para trabalhar com terrenos. Diversas funcionalidades de controle e comandos para customizar qualidade e performance. Assim, uma boa escolha trabalhar com esse tipo de cenrio, principalmente se voc vai ter cenrios bem grandes. Vamos estudar algumas das principais tcnicas para trabalhar com terrenos e obter o mximo proveito deles. Mas, o que um terreno? Os terrenos do Blitz3d so modelos especiais de objetos 3d com processamento dinmico. Terrenos so capazes de criar cenrios com qualidade de milhes de polgonos com apenas alguns milhares deles. Isso se d porque a engine do Blitz3d possui um sistema de composio inteligente desses objetos, aplicando o esforo de composio do mesmo nos locais frente e mais prximos da cmera. Abaixo temos o bitmap do terreno que corresponde ao seu mapa de relevo. As partes mais claras correspondem aos pontos mais altos e as partes mais escuras so os lugares mais baixos. a partir de uma imagem como essa que o Blitz3D vai construir o terreno.

tex=LoadTexture( "midia/floor.jpg" ) ScaleTexture tex, 10,10 EntityTexture terrain,tex,0,1 While Not KeyDown( 1 ) RenderWorld Flip Wend End

Como voc pode ver, o primeiro passo foi carregar um heightmap para transformar o mesmo em um terreno.
terrain=LoadTerrain( "midia/heightmap.bmp" )

Quando carregamos um mapa desses, ele vem com a altura dos relevos muito tnues, por isso devemos efetuar uma operao de escala para ajustar essa propriedade.
ScaleEntity terrain,1,30,1

Para o modelo no ficar todo branco, aplicamos uma textura para podermos visualizar a estrutura dele.
tex=LoadTexture( "midia/floor.jpg" ) ScaleTexture tex, 10,10 EntityTexture terrain,tex,0,1

Como voc pode ver, a aplicao da textura no gerou uma boa impresso. Isso se d pelo fato de todo o objeto estar coberto com a mesma imagem de mesma cor e saturao. Assim no temos as disformidades normais de um cenrio e nem variaes de cores. Mas todo programa criador de terrenos tambm da suporte a criao de super textura com blend de vrias texturas, colormaps e mapas de iluminao. Nesse prximo exemplo estamos criando um terreno e texturizando com uma super textura criada a partir do blend de vrias outras. Veja como a sensao de realismo muito superior. Exemplo 10
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,100,50,-20 RotateEntity camera, 30,0,0 light=CreateLight() RotateEntity light,90,0,0 terrain=LoadTerrain( "midia/heightmap.bmp" ) ScaleEntity terrain,1,30,1 tex=LoadTexture( "midia/Maptex.bmp" ) ScaleTexture tex, TerrainSize(terrain),TerrainSize(terrain ) EntityTexture terrain,tex,0,1 While Not KeyDown( 1 ) RenderWorld Flip Wend End

Carregando um terreno de uma imagem. Vamos a primeira coisa que devemos fazer: carregar um terreno. Para isso vamos usar o comando LoadTerrain. Exemplo 9
Graphics3D 640,480 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,100,50,-20 RotateEntity camera, 30,0,0 light=CreateLight() RotateEntity light,90,0,0 terrain=LoadTerrain( "midia/heightmap.bmp" ) ScaleEntity terrain,1,30,1

A super textura vai conter a colorao correspondente a cada localidade grfica do terreno, assim ela deve ser encaixada corretamente no mesmo. Para isso usamos uma tcnica especial.
ScaleTexture tex, TerrainSize(terrain),TerrainSize(terrain )

y#=EntityY(camera) z#=EntityZ(camera)

Depois pegamos a altura do terreno na posio em que a cmera est e adicionamos mais 5 unidades na altura, pois queremos deixa a cmera 5 unidades acima do terreno.
terra_y#=TerrainY(terrain,x#,y#,z#)+5

Por meio dessa tcnica deixamos a textura do mesmo tamanho que o terreno, pois estamos dizendo de devemos escalonar a textura com o mesmo tamanho do terreno. No prximo exemplo adicionamos controles de mobilidade, assim voc pode passear pelo cenrio. Exemplo 11
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,120,50,30 light=CreateLight() RotateEntity light,90,0,0 terrain=LoadTerrain( "midia/heightmap.bmp" ) ScaleEntity terrain,1,35,1 tex=LoadTexture( "midia/Maptex.bmp" ) ScaleTexture tex, TerrainSize(terrain),TerrainSize(terrain ) EntityTexture terrain,tex,0,1 While Not KeyDown( 1 ) If KeyDown( 205 )=True Then TurnEntity camera,0,-2,0 If KeyDown( 203 )=True Then TurnEntity camera,0,2,0 If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.2 If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.2 x#=EntityX(camera) y#=EntityY(camera) z#=EntityZ(camera) terra_y#=TerrainY(terrain,x#,y#,z#)+5 PositionEntity camera,x#,terra_y#,z# RenderWorld Text 0,0,"Use as teclas de cursor para andar" Flip Wend End

Por fim, foi s deixar a cmera nas mesmas posies x e z e passar ela pra altura que encontramos do acima, isso , a altura do terreno onde ela est + 5.
PositionEntity camera, x#, terra_y#, z#

Isso nos garante que vamos sempre estar andando em cima do terreno. Nvel de qualidade Um comando muito importante do sistema de terrenos do Blitz3d o TerrainDetail. Com ele podemos configurar a resoluo do terreno, isso , com quantos tringulos esse objeto ser criado e podemos ativar e desativar a opo vertex morph. A assinatura desse comando representada abaixo. TerrainDetail terreno, resoluo, vertexmorph A resoluo padro de um terreno 2000 tringulos, mas seria interessante voc deixar para o usurio decidir sobre isso. Assim voc pode criar 3 nveis de resoluo em uma aplicao. Uma baixa (1000) uma mdia (2000) e uma com alta resoluo (4000), dessa forma o usurio escolhe o que melhor se adaptar ao seu Hardware. A opo vertex morph boleana, portanto aceita os valores 0 para desativado e 1 para ativado. Esse dispositivo cria uma atenuao das arresta, dando efeito de suavizao no terreno. Imprescindvel para terrenos de baixa resoluo. O exemplo a seguir faz testes e mostra como usar o comando TerrainDetail. Exemplo 12
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,120,50,30 light=CreateLight() RotateEntity light,90,0,0 terrain=LoadTerrain( "midia/heightmap.bmp" ) ScaleEntity terrain,1,35,1 tex=LoadTexture( "midia/Maptex.bmp" ) ScaleTexture tex, TerrainSize(terrain),TerrainSize(terrain ) EntityTexture terrain,tex,0,1 Resolucao = 2000

Estamos usando as setas direcionais para controlar o movimento.


If KeyDown( 205 camera,0,-2,0 If KeyDown( 203 camera,0,2,0 If KeyDown( 208 camera,0,0,-0.2 If KeyDown( 200 camera,0,0,0.2 )=True Then TurnEntity )=True Then TurnEntity )=True Then MoveEntity )=True Then MoveEntity

O passo seguinte foi pegar as coordenadas atuais da cmera e colocar em variveis.


x#=EntityX(camera)

Vertex = 0 While Not KeyDown( 1 ) TerrainDetail terrain, Resolucao, Vertex If KeyHit(57) Then Vertex = Not Vertex If KeyDown(44) Then Resolucao = Resolucao - 10 If KeyDown(45) Then Resolucao = Resolucao + 10 If KeyDown( 205 )=True Then TurnEntity camera,0,-2,0 If KeyDown( 203 )=True Then TurnEntity camera,0,2,0 If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.2 If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.2 x#=EntityX(camera) y#=EntityY(camera) z#=EntityZ(camera) terra_y#=TerrainY(terrain,x#,y#,z#)+5 PositionEntity camera,x#,terra_y#,z# RenderWorld Text 0,0, "Use as teclas de cursor para andar" Text 0,12, "Use Space para Ligar e Desligar Vertex Morph" Text 0,24, "Use Z e X para aumentar e diminuir a resoluo" Text 0,50, "RESOLUO: " + Resolucao + " Vertex Morph: " + Vertex Flip Wend End

Talvez voc ache que s a super textura no conseguiu gerar uma imagem muito detalhada do terreno, voc pode ento criar camadas de textura, ou para melhorar a resoluo da imagem ou para dar efeitos especiais a ela. No exemplo a seguir, usamos uma imagem do exemplo do avio de Mark Sibly para criar um efeito mais de realismo no terreno, pois cria o efeito de rachaduras.

Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,120,50,30 light=CreateLight() RotateEntity light,90,0,0 terrain=LoadTerrain( "midia/heightmap.bmp" ) ScaleEntity terrain,1,35,1 tex=LoadTexture( "midia/Maptex.bmp" ) ScaleTexture tex, TerrainSize(terrain),TerrainSize(terrain ) EntityTexture terrain,tex,0,2 tex2 = LoadTexture( "midia/filtro.jpg" ) ScaleTexture tex2,20,20 EntityTexture terrain,tex2,0,1 While Not KeyDown( 1 ) If KeyDown( 205 )=True Then TurnEntity camera,0,-2,0 If KeyDown( 203 )=True Then TurnEntity camera,0,2,0 If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.2 If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.2 x#=EntityX(camera) y#=EntityY(camera) z#=EntityZ(camera) terra_y#=TerrainY(terrain,x#,y#,z#)+5 PositionEntity camera,x#,terra_y#,z# RenderWorld Text 0,0, "Use as teclas de cursor para andar" Flip Wend End

Agora, e sua vez! Adicione objetos, rvores, casas e carros ao terreno e veja o resultado. Cmeras Como sabemos, um cenrio 3d no nada sem uma cmera. Ela nossos olhos, que nos mostra os objetos 3d que existem. As cmeras possuem uma srie de propriedades e podemos implementar vrios efeitos especiais como zoom e fog. Vamos estudar algumas dessas propriedades. Abaixo um exemplo simples de criao de cmera. Como voc j sabe, uma cmera criada pelo mtodo CreateCamera. Exemplo 14
Graphics3D 640,480 SetBuffer BackBuffer() light=CreateLight() camera=CreateCamera() cubo=CreateCube() PositionEntity cubo,0,0,5 While Not KeyDown( 1 ) TurnEntity cubo,0,1,0 RenderWorld Flip Wend

Exemplo 13

End

Fog O efeito de fog tem duas finalidades: criar efeito de neblina e economizar processamento. Para fazer com que o Fog seja ativado, primeiro voc deve dizer qual ser a rea de influncia do Fog, o Range, por meio do comando CameraFogRang. Veja abaixo a assinatura desse comando. CameraFogRang cmera, inicio, fim O valor inicial a distncia prxima cmera onde o efeito comea. O segundo valor, o final, onde o efeito termina, isso , onde a neblina fica to intensa que nada mais pode ser visualizado. Esse comando apenas especifica os atributos de Fog, mas no o aciona. Para ligarmos o efeito de fog devemos usar o comando CameraFogMode. Veja a assinatura desse comando. CameraFogMode cmera, modo Vamos a um exemplo prtico... Exemplo 15
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,1,0 CameraFogRange camera,1,10 light=CreateLight() RotateEntity light,90,0,0 plano=CreatePlane() tex=LoadTexture( "midia/floor.jpg" ) EntityTexture plano,tex modo = 0 While Not KeyDown( 1 ) CameraFogMode camera, modo If KeyHit(57) Then modo = Not modo If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0 If KeyDown( 203 )=True Then TurnEntity camera,0,1,0 If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.05 If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.05 RenderWorld Text 10,10, "SPACE-> Liga desliga Fog SETAS-> caminha pelo cenrio" Flip Wend End

voc queira uma neblina com uma cor mais viva, como verde ou vermelho para simular um efeito de gs qumico. Para isso temos o comando CameraFogColor. CameraFogColor cmera, vermelho, verde, azul Exemplo 16
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() PositionEntity camera,0,1,0 CameraFogRange camera,1,10 CameraFogColor camera,100,100,100 CameraFogMode camera, 1 light=CreateLight() RotateEntity light,90,0,0 plano=CreatePlane() tex=LoadTexture( "midia/floor.jpg" ) EntityTexture plano,tex While Not KeyDown( 1 ) If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0 If KeyDown( 203 )=True Then TurnEntity camera,0,1,0 If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.05 If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.05 RenderWorld Text 10,10, "SETAS-> caminha pelo cenrio" Flip Wend End

Nesse exemplo colocamos a saturao de cada cor em 100 da criamos uma colorao cinza para o efeito de fog.
CameraFogColor camera,100,100,100

O primeiro passo foi configura o inicio da neblina para uma unidade de medida a frente da cmera e o fim do efeito para dez frente.
CameraFogRange camera,1,10

A linha a seguir liga e desliga o efeito


CameraFogMode camera, modo

Como voc viu o efeito de fog s atuou sobre as reas onde haviam entidades sendo exibidas. Caso voc possua um cenrio Indoor, isso , interno, isso no ser problema, pois haver paredes para todos os lados. Para jogos em cenrios abertos voc poder ter situaes onde utilize um skybox ou um skydome e assim tambm haver objetos 3d por todos os lados. Mas se quiser economizar o processamento mesmo, poder eliminar esses recursos e configura a cor de fundo da cmera para ficar com a mesma cor do fog. Podemos fazer isso por meio do comando CameraClsColor. Esse comando funciona assim: CameraClsColor cmera, vermelho, verde, azul Exemplo 17
Graphics3D 800,600 SetBuffer BackBuffer()

Neblinas normalmente no possuem colorao preta; so de cor cinza. Mas talvez

camera=CreateCamera() PositionEntity camera,0,1,0 CameraClsColor camera,100,100,100 CameraFogRange camera,1,10 CameraFogColor camera,100,100,100 CameraFogMode camera, 1 light=CreateLight() RotateEntity light,90,0,0 plano=CreatePlane() tex=LoadTexture( "midia/floor.jpg" ) EntityTexture plano,tex While Not KeyDown( 1 ) If KeyDown( 205 )=True Then TurnEntity camera,0,-1,0 If KeyDown( 203 )=True Then TurnEntity camera,0,1,0 If KeyDown( 208 )=True Then MoveEntity camera,0,0,-0.05 If KeyDown( 200 )=True Then MoveEntity camera,0,0,0.05 RenderWorld Text 10,10, "SETAS-> caminha pelo cenrio" Flip Wend End

If KeyDown( 208 )=True Then MoveEntity cam1,0,0,-0.05 If KeyDown( 200 )=True Then MoveEntity cam1,0,0,0.05 RenderWorld Text 0,0,"SETAS-> Move Camera1" Flip Wend End

Veja que criamos duas cmeras e colocamos uma ao lado da outra:


cam1=CreateCamera() CameraViewport cam1,0,0,399,600 cam2=CreateCamera() CameraViewport cam2,401,0,399,600

Mas s a primeira cmera ser animada, isso , obedecer aos comandos do teclado.
If KeyDown( 205 cam1,0,-1,0 If KeyDown( 203 cam1,0,1,0 If KeyDown( 208 cam1,0,0,-0.05 If KeyDown( 200 cam1,0,0,0.05 )=True Then TurnEntity )=True Then TurnEntity )=True Then MoveEntity )=True Then MoveEntity

Aqui est nosso comando que muda a cor de fundo da cmera.


CameraClsColor camera,100,100,100

reas de viso Por meio do comando CameraViewPort podemos configurar a rea de viso de uma ou mais cmeras. Dessa forma, alm de configurar a rea de viso, podemos usar esse comando para configura duas ou mais cmeras em uma aplicao. CameraViewport camera, posiox, posioy, largura, altura Podemos com ele configurar onde a rea de exibio se inicia (posiox e posioy) e quais sero as dimenses dessa rea de viso da cmera. Exemplo 18
Graphics3D 800,600 SetBuffer BackBuffer() cam1=CreateCamera() CameraViewport cam1,0,0,399,600 cam2=CreateCamera() CameraViewport cam2,401,0,399,600 light=CreateLight() RotateEntity light,90,0,0 plane=CreatePlane() grass_tex=LoadTexture( "midia/floor.jpg" ) EntityTexture plane,grass_tex PositionEntity plane,0,-1,0 While Not KeyDown( 1 ) If KeyDown( 205 )=True Then TurnEntity cam1,0,-1,0 If KeyDown( 203 )=True Then TurnEntity cam1,0,1,0

Limite de viso Quando criamos uma cmera, ela possui um limite de viso, um Ranger. Esse limite padro do ponto 1 at o 1.000. Se necessitarmos mudar esses valores podemos usar o comando CameraRange. CameraRange cmera, incio, fim Com esse comando podemos declarar de onde se iniciar a exibio e at onde ela vai alcanar. Esse comando pode ser muito importante para aumentar o desempenho de uma aplicao, pois se ns diminuirmos a amplitude de viso da cmera, teremos menos objetos sendo renderizados. Exemplo 19
Graphics3D 800,600 SetBuffer BackBuffer() cam=CreateCamera() light=CreateLight() plane=CreatePlane() grass_tex=LoadTexture( "midia/floor.jpg" ) EntityTexture plane,grass_tex PositionEntity plane,0,-5,0 ini = 1 fim = 1000 While Not KeyDown( 1 ) If KeyHit(57) ini = Rnd(0,25) fim = Rnd(100,300) CameraRange cam, ini, fim EndIf If KeyDown( 205 )=True Then TurnEntity cam,0,-1,0 If KeyDown( 203 )=True Then TurnEntity cam,0,1,0

If KeyDown( 208 )=True Then MoveEntity cam,0,0,-0.05 If KeyDown( 200 )=True Then MoveEntity cam,0,0,0.05 RenderWorld Text 0, 0,"SPACE -> Sorteia nova Aplitude" Text 0, 20, "Alcance da camera => INICIO: " + ini + " FIM: " + fim Flip Wend End

Wend End

Nesse exemplo criamos duas variveis para controlar os valores iniciais e finais da rea de viso da cmera.
ini = 1 fim = 1000

Iluminao A iluminao algo muito importante em um jogo. Se o seu correto controle fica difcil criar realismo nas cenas e ela tambm fundamental para criar efeitos especiais. Alm da iluminao ambiente, o Blitz3d possui 3 tipos de emissores de luz. Vamos estudar esses 4 fatores e algumas formas de trabalhar com eles. AmbienteLight Quando iniciamos uma cena 3d o Blitz3d j configura a iluminao ambiente da cena automaticamente para uma saturao 127, 127, 127. Veja nesse exemplo que mesmo sem criar uma fonte de emisso de luz, existe uma certar iluminao acinzentada no cenrio. Exemplo 21
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() sphere=CreateSphere( 32 ) PositionEntity sphere,0,0,5 While Not KeyDown( 1 ) RenderWorld Flip Wend End

Quando pressionamos a tecla space (57) os valores das variveis so sorteados e ocorre a execuo do comando de alterao da amplitude da cmara com os novos valores.
If KeyHit(57) ini = Rnd(0,25) fim = Rnd(100,300) CameraRange cam, ini, fim EndIf

Efeito de Zoom Por meio do comando CameraZoom conseguimos gerar um efeito de zoom na cmera. Isso pode ser bastante interessante para jogos de tiro onde o armamento possui luneta, ou ento para simular o uso de binculos. Esse comando muito simples, pois s recebe dois parmetros: a cmera na qual desejamos implementar o zoom e a intensidade do efeito. Exemplo 20
Graphics3D 800,600 SetBuffer BackBuffer() cam=CreateCamera() light=CreateLight() plane=CreatePlane() grass_tex=LoadTexture( "midia/floor.jpg" ) EntityTexture plane,grass_tex PositionEntity plane,0,-5,0 zoom# = 1 While Not KeyDown( 1 ) If KeyDown(44) zoom# =zoom# + 0.01 CameraZoom cam, zoom# EndIf If KeyDown(45) zoom# =zoom# - 0.01 CameraZoom cam, zoom# EndIf RenderWorld Text 0, 0,"Z -> Zoom + X -> Zoom -" Text 0, 20, "ZOOM => " + zoom# Flip

Essa saturao a padro do Blitz3d. Mas se quisermos, por exemplo, criar um efeito de escurido, deveremos deixar a iluminao ambiente mais escura. Para mudarmos a iluminao ambiente usamos o comando AmbienteLight. Esse comando aceita trs parmetros que so as saturaes red, green, blue do formato de cor RGB. No Exemplo abaixo usamos um gerador de valores randmicos para sortear a intensidade de cada por e aplicar ao ambiente. Exemplo 22
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() sphere=CreateSphere( 32 ) PositionEntity sphere,0,0,5 r=127 g=127 b=127 While Not KeyDown( 1 ) If KeyHit(57) r = Rnd(0,255) g = Rnd(0,255)

b = Rnd(0,255) AmbientLight r,g,b EndIf RenderWorld Text 0,0,"SPACE -> Sorteia Nova Iluminao Ambiente" Text 0,20,"Red: " + r + " Green: " + g + " Blue: " + b Flip Wend End

Criando Luzes Por meio do comando CreateLight do Blitz3D podemos criar 3 tipos de fontes emissoras de luz. CreateLight( ) comando padro, cria uma luz direcional. CreateLight(1) cria luz direcional (directional). CreateLight(2) cria um ponto de luz (point). CreateLight(3) cria uma luz em cone (spot). A luz direcional como a luz do sol, iluminando tudo. Elas possuem uma posio infinita e alcance infinito, portanto atingem todos os objetos da mesma forma. O ponto de luz como uma lmpada, tambm chamada de Omni em modeladores 3d. Ela opera como uma lmpada comum de residncia, dessas redondas. Ilumina tudo ao redor a partir de um ponto, mas sua intensidade vai diminuindo com a distncia. A iluminao do tipo cone, ou spot uma iluminao em forma de cone. Possui um ngulo inicial de iluminao e um ngulo final. Vamos criar um ambiente de testes para essas lmpadas. Exemplo 23
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera() AmbientLight 0,0,0 bola=CreateSphere( 32 ) PositionEntity bola,0,0,5 parede1=CreateCube() PositionEntity parede1,-3,0,5 ScaleMesh parede1, .5, 2, 5 parede2 =CopyMesh(parede1) PositionEntity parede2, 3,0,5 parede3 =CopyMesh(parede1) PositionEntity parede3, 0,0,10 RotateEntity parede3, 0, 90,0 tipo = 2 LUZ = CreateLight(2,bola) LightRange luz, 3 PositionEntity luz, 2, 0, 0

LightColor luz, 0,255,0 While Not KeyDown( 1 ) TurnEntity bola, 0, 1, 0 If KeyHit(57) r = Rnd(0,255) g = Rnd(0,255) b = Rnd(0,255) ntipo = Rnd(1,3) If ntipo <> tipo FreeEntity luz LUZ = CreateLight(ntipo,bola) LightRange luz, 3 PositionEntity luz, 2, 0, 0 tipo = ntipo EndIf LightColor luz, r,g,b EndIf RenderWorld Text 0,0,"SPACE -> Sorteia Nova Cor e Tipo" Text 0,20,"Red: " + r + " Green: " + g + " Blue: " + b If tipo = 1 Then Text 0, 40, "TIPO: Direcional" If tipo = 2 Then Text 0, 40, "TIPO: Omni" If tipo = 3 Then Text 0, 40, "TIPO: Spot" Flip Wend End

Veja que, para intensificar o efeito da luz, deixamos a luz ambiente apagada, isso , configuramos seu valor para preto 0,0,0.
AmbientLight 0,0,0

Estamos criando uma luz inicial do tipo Omni, sendo ela filha do objeto bola. Fizemos isso para rotacion-la de forma mais simples.
LUZ = CreateLight(2,bola)

Estamos usando o comando LightRange para configurar o raio de alcance dela para 3, assim criaremos efeito de sombra e intensidade de iluminao pois a luz vai atingir um mesmo ambiente em intensidade diferente de acordo com a distncia. O valor padro para range 1000, se ns deixssemos esse valor, todo o cenrio seria ilumidado com mesma intensidade de luz.
LightRange luz, 3

Como criamos a luz como filha do objeto bola, ele est na mesma posio dela, por isso devemos deslocar a mesma um pouco.
PositionEntity luz, 2, 0, 0

Estamos configurando a cor inicial da luz para verde.


LightColor luz, 0, 255, 0

Dentro do loop, estamos rotacionando a luz por meio da esfera. Como a luz uma entidade filha dessa, ela receber os mesmos comandos automaticamente. Quando deslocamos a luz, no deslocamos o piv dela, portanto, o efeito de rotao dela

se dar no mesmo eixo da bola, causando um efeito de translao, assim como os planetas fazem em redor do sol.
TurnEntity bola, 0, 1, 0

Quando apertamos a barra de espao vamos sortear uma nova cor e um novo tipo de luz. Para mudar a luz, tivemos de destruir a entidade anterior e criar uma nova com os dados sorteados, mas s fazemos isso se a nova de um tipo diferente da anterior.
If KeyHit(57) r = Rnd(0,255) g = Rnd(0,255) b = Rnd(0,255) ntipo = Rnd(1,3) If ntipo <> tipo FreeEntity luz LUZ = CreateLight(ntipo,bola) LightRange luz, 3 PositionEntity luz, 2, 0, 0 tipo = ntipo EndIf LightColor luz, r,g,b EndIf

desempenho e poder implementar alguns efeitos extras em seus jogos. No exemplo abaixo estamos criando um efeito de neve por meio de diversos sprites de esferas. Veja que embora temos milhares de objetos na tela, a quantidade de polgonos renderizados bem baixa. Exemplo 24
Graphics3D 640,480 Type Tneve Field sprite Field px# Field py# Field pz# End Type cam = CreateCamera() MoveEntity cam,0,3,-10 Global floco = LoadSprite("midia/floco.png") ScaleSprite floco, 0.1, 0.1 HideEntity floco While Not KeyDown(1) Criar() t = Mover() UpdateWorld RenderWorld Color 255,0,0 Text 0,0, "FLOCOS: " + t Text 0,20, "TOTAL DE POLIGONOS: " + TrisRendered() Flip Wend End Function Criar() For k = 1 To 5 y# = 10 x# = Rnd (-10,10) z# = Rnd (-10,10) flocos.Tneve = New Tneve flocos\sprite = CopyEntity(floco) flocos\px# = x# flocos\py# = y# flocos\pz# = z# Next End Function Function mover() For this.Tneve =Each Tneve this\py# = this\py# - 0.02 PositionEntity this\sprite, this\px#, this\py#, this\pz# If this\py# < 0 FreeEntity this\sprite Delete this EndIf x = x + 1 Next Return x End Function

Sprites Sprites so entidades 2d presentes em um ambiente 3d. Eles nada mais so que imagens inseridas em um ambiente tridimencional. Eles possuem a caracterstica especial de sempre estarem com sua face voltada para a cmera, assim ningum ir perceber que ele plano. Os sprites so comumente usados para 3 finalidades bsicas: 1. criar efeitos de partculas. 2. gerar cenrios mais leves para economia de processamento. 3. criao de jogos 2d com acelerao grfica. Como elemento bsico para partculas sua usabilidade muito obvia, afinal um sprite possui apenas 2 polgonos e pode conter uma imagem muito complexa, que gastaria dezenas ou at centenas de polgonos para ser criada em 3d. Como partculas no muitssimas em um cenrio (imagine neve ou chuva), s por meio de sprites possvel criar esse tipo de efeito. Tambm podemos usar sprites em objetos do cenrio para deixar a aplicao mais leve. O mais comum o uso para criar rvores e outras vegetaes. Talvez voc deseje criar um jogo estilo 2d, mas necessita de alguns efeitos especiais, ou uma melhor perspectiva grfica. Usando sprites voc ter um alto poder de

Veja que criamos um type para gerenciar as entidades. Isso muito importante num efeito de partculas, pois os types no possuem limite preestabelecido de entidades, assim podemos criar a quantidade que quisermos.

Type Tneve Field sprite Field px# Field py# Field pz# End Type

End Function

Carregamos a primeira entidade base de sprite que servir de cpia para todas as outras e demos o comando Hide para escond-la da tela.
Global floco = LoadSprite("midia/floco.png") ScaleSprite floco, 0.1, 0.1 HideEntity floco

Essa funo usa o loop For/Each para percorrer todas as instncias de um Type, assim podemos controlar todos os flocos de neve de uma vez s. A primeira coisa que fazemos mover o floco um pouco para baixo.
this\py# = this\py# - 0.02 PositionEntity this\sprite, this\px#, this\py#, this\pz#

O nosso loop se inicia com a invocao da funo Criar().


Criar()

Vamos analisar essa funo:


Function Criar() For k = 1 To 5 y# = 10 x# = Rnd (-10,10) z# = Rnd (-10,10) flocos.Tneve = New Tneve flocos\sprite = CopyEntity(floco) flocos\px# = x# flocos\py# = y# flocos\pz# = z# Next End Function

Depois disso, verificamos se o floco passou do ponto zero, isso , chegou ao cho, em um jogo a melhor opo seria verificar a coliso com o terreno, e se chegou ao final, deletamos a sprite e destrumos a instncia do type.
If this\py# < 0 FreeEntity this\sprite Delete this EndIf

Para descobrir a quantidade de flocos de neve atuais colocamos um contador dentro do lao For/Each.
x = x + 1

Por fim retornamos o valor encontrado.


Return x

Ela se inicia com um lao de 5 iteraes, portanto estamos criando 5 entidades em cara iterao do loop. Isso d mais ou menos 300 entidades por segundo, j que a velocidade da engine est limitada velocidade de retrao do monitor (60). Colocamos a posio inicial y como 10 y# = 10. As posies x e z so aleatrias, so dadas por meio do comando de randomizao Rnd (-10,10). A partir disso, criamos a instncia de floco e atribumos a eles os valores para cada campo. Nesse momento, o controle do programa volta para o loop principal e a segunda funo chamada.
t = Mover()

Por fim, restou renderizar a cena e exibir as informaes.


UpdateWorld RenderWorld Color 255,0,0 Text 0,0, "FLOCOS: " + t Text 0,20, "TOTAL DE POLIGONOS: " + TrisRendered() Flip

Vamos dar um exemplo agora de uso de sprites para criar vegetao. Exemplo 25
Graphics3D 800,600 SetBuffer BackBuffer() cam=CreateCamera() light=CreateLight() plane=CreatePlane() tex=LoadTexture( "midia/floor.jpg" ) EntityTexture plane,tex PositionEntity plane,0,-2,0 Dim moita(2000) moita(0) = LoadSprite("midia\moita.png",2) ScaleSprite moita(0), .5, .5 For k = 1 To 2000 x = Rnd(-10, 10) y = -1 z = Rnd(-10,10) moita(k) = CopyEntity(moita(0)) PositionEntity moita(k), x, y, z Next While Not KeyDown( 1 ) If KeyDown( 205 )=True Then TurnEntity cam,0,-1, 0 If KeyDown( 203 )=True Then TurnEntity cam,0, 1, 0

Perceba que essa funo retorna um valor, a quantidade de flocos que existe atualmente. Vamos a funo em si.
Function mover() For this.Tneve =Each Tneve this\py# = this\py# - 0.02 PositionEntity this\sprite, this\px#, this\py#, this\pz# If this\py# < 0 FreeEntity this\sprite Delete this EndIf x = x + 1 Next Return x

If KeyDown( 208 )=True Then MoveEntity cam,0, 0,-.2 If KeyDown( 200 )=True Then MoveEntity cam,0, 0, .2 RenderWorld Text 0, 0, "SETAS -> andam pelo cenrio" Text 0, 20,"POLIGONOS RENDERIZADOS: " + TrisRendered() Flip Wend End

Dessa vez carregamos o sprite com a flag 2, afinal no seria nada bom que eles fossem transparentes.
moita(0) = LoadSprite("midia\moita.png",2)

Uma das vantagens de poder usar sprites poder fazer operaes com eles que no poderamos fazer com objetos 2d, por exemplo, rotao em tempo real. Com o comando RotateSprite podemos rotacionar um sprite no sentido horrio ou anti-horrio, isso , no eixo z. Exemplo 26
Graphics3D 800,600 SetBuffer BackBuffer() cam=CreateCamera() light=CreateLight() ob = LoadSprite("midia\conc02.jpg") PositionEntity ob, 0,0,2 While Not KeyDown( 1 ) If KeyDown( 203 ) Then rot = rot + 1 If KeyDown( 205 ) Then rot = rot - 1 RotateSprite ob, rot RenderWorld Text 0, 0, "SETAS Esquerda e Direita rotaciona o Sprite" Flip Wend End

PositionEntity camera,0,0,-10 light=CreateLight() pivo=CreatePivot() bola=CreateSphere(16,pivo) PositionEntity bola,1,0,0 EntityColor bola, 255,0,0 bola2=CreateSphere(16,pivo) PositionEntity bola2,4,2,0 EntityColor bola2, 0,255,0 bola3=CreateSphere(16,pivo) PositionEntity bola3,7,-1,0 EntityColor bola3, 0,0,255 While Not KeyDown(1) TurnEntity pivo,0,1,0 RenderWorld Flip Wend End

Pivot Um piv uma entidade invisvel no cenrio 3d sua funcionalidade prover um pai para outro objeto em uma hierarquia, podendo ser usado para controlar as entidades filhas, sendo deu centro de rotao. Caso voc decida criar uma entidade atravs de vrtices e malhas, voc poder manipular todas essas entidades apenas por meio do piv. No exemplo abaixo criamos um pivot e passamos este como entidade pai das esferas criadas posteriormente. Assim, basta rotacionar o piv que as trs esferas so rotacionadas juntas. Exemplo 27
Graphics3D 800, 600 SetBuffer BackBuffer() camera=CreateCamera()

Som 3d Um som 3d um som com posio geogrfica dentro e um cenrio. Quanto mais prximo estamos da fonte emissora do som, mais alto ser o volume com o qual o escutamos. Para controlar sons 3d o Blitz3D possui 3 comandos: Load3Dsound -> carrega um som como entidade 3d. CreateListener -> configura uma entidade como ouvinte do som. EmitSound -> emite um som 3d. O primeiro comando no possui novidades, s devemos passar a ele o som que dever ser carregado. Som3d = Load3DSound(umsom.wav) Para que possamos criar a sensao de distancia, devemos criar um ouvinte, a entidade que escuta o som, para isso normalmente usamos a cmera pai do ouvinte, pois ela representa a nossa posio no cenrio 3d e assim o ouvinte a seguir. No segundo parmetro temos a perda por distncia, onde o valor padro 1. Quanto menor esse valor, mais distante o som poder ser ouvido. Ouvinte = CreateListener(camera,perda) Um som 3d emitido por uma entidade 3d, por isso o comando EmitSound recebe o som a ser emitido e o objeto emissor, para que esse som seja emitido no local onde est esse objeto. EmitSound(som3d, ObjetoEmissor) Exemplo 28
Graphics3D 800,600 SetBuffer BackBuffer() camera=CreateCamera()

PositionEntity camera,0,5,-10 light=CreateLight() RotateEntity light,90,0,0 cenario=LoadMesh("midia/cenariobase.3ds" ) radio =LoadMesh("midia/cdplay.3ds") PositionEntity radio, 15, 1.1, 20 ScaleEntity radio, 5,5,5 fone=CreateListener(camera,0.2) som=Load3DSound("midia/beep1.wav") While Not KeyDown(1) If KeyDown(205)=True Then TurnEntity camera,0,-1, 0 If KeyDown(203)=True Then TurnEntity camera,0, 1, 0 If KeyDown(208)=True Then MoveEntity camera,0, 0,-0.05 If KeyDown(200)=True Then MoveEntity camera,0, 0, 0.05 x = x + 1 If x = 60 x = 0 EmitSound(som,radio) EndIf RenderWorld Text 0,0,"Use Setas Para Mover" Text 0,20,"Va at o Radio, o Som vai aumentando o volume" Flip Wend End

Criamos um ouvinte filho da cmera e com perda de 0.2.


fone=CreateListener(camera,0.2)

Configuramos o modelo 3d de rdio para ser o emissor do som


EmitSound(som,radio)

Prticas Vamos agora explicar como implementar algumas coisas teis em jogos 3d. Isso , como implementar algumas funcionalidades bsicas. Fazer a camera seguir o personagem Para fazer com que uma cmera siga um personagem basta declarar a cmera como filha do personagem a ser seguido. Obj = Loadmesh(obj.b3d) camera = CreateCamera(Obj) Depois s posicionar a cmera na distancia certa do personagem e dar uma ligeira inclinao para ela apontar para o lugar certo. MoveEntity camera, 0, 5, 10 RotateEntity camera, 30,0,0 A partir desse momento s controlarmos o personagem que a cmera o segue. Exemplo 29
Graphics3D 800,600 SetBuffer BackBuffer()

heroy = LoadAnimMesh("midia/ninja.b3d") ScaleEntity heroy, .1, .1, .1 PositionEntity heroy, 20,0,30 parado = ExtractAnimSeq(heroy,4,4) andando = ExtractAnimSeq(heroy,1,14) anima = 0 camera=CreateCamera(heroy) MoveEntity camera, 0, 10,-10 RotateEntity camera, 20,0,0 light=CreateLight() terrain=LoadTerrain( "midia/heightmap.bmp" ) ScaleEntity terrain,1,35,1 tex=LoadTexture( "midia/Maptex.bmp" ) ScaleTexture tex, TerrainSize(terrain),TerrainSize(terrain ) EntityTexture terrain,tex,0,1 While Not KeyDown( 1 ) If KeyDown( 205 ) Then TurnEntity heroy,0,-1,0 If KeyDown( 203 ) Then TurnEntity heroy,0, 1,0 If KeyDown( 200 ) MoveEntity heroy,0,0, 0.1 If Animate = 0 Then Animate heroy, 1, 0.2, andando Animate = 1 Else Animate heroy, 1, 0.2, parado Animate = 0 EndIf x#=EntityX(heroy) y#=EntityY(heroy) z#=EntityZ(heroy) terra_y#=TerrainY(terrain,x#,y#,z#) PositionEntity heroy,x#,terra_y#,z# UpdateWorld RenderWorld Text 0,0,"Use as teclas de cursor para andar" Flip Wend End

Primeiro criamos o nosso heri


heroy = LoadAnimMesh("midia/ninja.b3d") ScaleEntity heroy, .1, .1, .1 PositionEntity heroy, 20,0,30

Extramos as animaes que vamos usar e criamos uma varivel para o controle das animaes.
parado = ExtractAnimSeq(heroy,4,4) andando = ExtractAnimSeq(heroy,1,14) anima = 0

A seguir, criamos a carmera como filha do Heri, e colocamos a mesma a uma certa distncia, olhando para o heri.
camera=CreateCamera(heroy) MoveEntity camera, 0, 10,-10 RotateEntity camera, 20,0,0

Se pressionarmos as setas para esquerda e para direita, o heri ser rotacionado e como a cmera sua filha, vai acompanhar o heri.
If KeyDown( 205 ) Then TurnEntity heroy,0,-1,0

If KeyDown( 203 ) Then TurnEntity heroy,0, 1,0

O passo mais complexo e animar o personagem se ele estiver indo pra frente.
If KeyDown( 200 ) MoveEntity heroy,0,0, 0.1 If Animate = 0 Then Animate heroy, 1, 0.2, andando Animate = 1 Else Animate heroy, 1, 0.2, parado Animate = 0 EndIf

esfera criada para auxiliar na coliso do personagem.

Se a seta para cima for pressionada o heri ser movido para frente:
MoveEntity heroy,0,0, 0.1

Se a animao de andar no estiver ativa, ento rodamos essa animao.


If Animate = 0 Then Animate heroy, 1, 0.2, andando

Os passos seguintes so: criar a entidade de coliso baseada nessa esfera e configurar o canal alfa para que a esfera fique invisvel. Exemplo 30
Graphics3D 800,600 SetBuffer BackBuffer() Const COLIDE_HEROI = 1 Const COLIDE_CENARIO = 2 CX = CreateSphere() ScaleMesh CX, 1.5,5.5,1.5 PositionEntity CX, 0,5,10 EntityType CX, COLIDE_HEROI EntityRadius CX, 1.5, 5.5 EntityAlpha CX, 0 heroy = LoadAnimMesh("midia/ninja.b3d",CX) MoveEntity heroy, 0,-5,0 parado = ExtractAnimSeq(heroy,4,4) andando = ExtractAnimSeq(heroy,1,14) anima = 0 camera=CreateCamera(heroy) MoveEntity camera, 0, 20,-20 RotateEntity camera, 20,0,0 light=CreateLight() RotateEntity light, 90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) EntityType cenario, COLIDE_CENARIO Collisions COLIDE_HEROI, COLIDE_CENARIO, 2, 2 While Not KeyDown( 1 ) If KeyDown( 205 ) Then TurnEntity CX,0,1,0 If KeyDown( 203 ) Then TurnEntity CX,0, 1,0 If KeyDown( 200 ) MoveEntity CX,0,0, 0.1 If Animate = 0 Then Animate heroy, 1, 0.2, andando Animate = 1 Else Animate heroy, 1, 0.2, parado Animate = 0 EndIf UpdateWorld RenderWorld Text 0,0,"Use as teclas de cursor para andar"

Se a tecla para cima no estiver sendo apertada, ento o heroy dever estar parado e a animao exibir esse estado.
Animate heroy, 1, 0.2, parado

Colises com o cenrio Quando formos trabalhar com sistema de colises podem surgir alguns inconvenientes.O sistema automtico de colises do Blitz3D sempre cria colises por esfera para o objeto principal, mas no podemos reposicionar essa esfera, podemos apenas aumentar o tamanho de seu raio x e y. O problema aparece quando queremos inserir um personagem animado. Ao criar a esfera de colises, isso vai ser feito onde estiver o pivot do personagem, e normalmente o pivot dele em seus ps, da o centro da esfera de colises ser o p do personagem. Resultado, ele no consegue subir uma mnima elevao, s vezes at empurrando para baixo do cenrio. O correto ajustar o pivot do modelo 3d em um software de modelagem 3d, mas nem sempre isso possvel. Para resolver esse problema uso a tcnica de criar um objeto auxiliar para a coliso, da eu crio o heri como filho desse objeto, herdando o comportamento do objeto pai. O objeto auxiliar deve ter as mesmas dimenses do modelo animado para no gerar efeitos desagradveis. Para visualizar melhor como deveremos ajustar os raios da entidade de colises, eu crio uma objeto auxiliar de uma esfera, da s passar os mesmos dados para a entidade de coliso. Veja abaixo uma imagem da

Flip Wend End

A primeira coisa que fizemos foi criar os tipos de entidades de colises


Const COLIDE_HEROI = 1 Const COLIDE_CENARIO = 2

Os comando de movimentao e rotao so aplicados na esfera e no no modelo 3d, afinal por meio dela que estamos controlando as colises e fsica. O modelo 3d recebe os comportamentos por herana.
If KeyDown( 205 ) Then TurnEntity CX,0,1,0 If KeyDown( 203 ) Then TurnEntity CX,0, 1,0

Criamos uma esfera para auxiliar nas colises e ajustamos o tamanho dela para que fiquem do mesmo tamanho que o nosso modelo animado.
CX = CreateSphere() ScaleMesh CX, 1.5, 5.5, 1.5

Ajustamos a posio da esfera no cenrio


PositionEntity CX, 0,5,10

Configuramos o tipo de objeto de coliso da esfera. Ela ser responsvel pela coliso do heri.
EntityType CX, COLIDE_HEROI

Escadas e rampas Agora que criamos o nosso sistema auxiliar de colises, subir escadas e rampas muito fcil. Nesse novo exemplo apenas adicionamos um objeto novo no cenrio anterior.

Ajustamos os raios da entidade de coliso da esfera que fique com o mesmo tamanho da esfera. Como voc se lembra, ao ser criada essa entidade possui raios 1,1.
EntityRadius CX, 1.5, 5.5

Deixamos a esfera auxiliar invisvel


EntityAlpha CX, 0

Ao criar o modelo animado do heri, dizemos que ele ser filho da esfera auxiliar de colises.
heroy = LoadAnimMesh("midia/ninja.b3d",CX)

Ajustamos a posio do modelo animado para que se ajuste posio da esfera, afinal o centro dele no p e a esfera tem seu centro em seu meio. Assim, ao ser criado como filho da esfera, ele ter seu p no meio da esfera.
MoveEntity heroy, 0,-5,0

Exemplo 31
Graphics3D 800,600 SetBuffer BackBuffer() Const COLIDE_HEROI = 1 Const COLIDE_CENARIO = 2 CX = CreateSphere() ScaleMesh CX, 1.5,5.5,1.5 PositionEntity CX, 0,5,-10 EntityType CX, COLIDE_HEROI EntityRadius CX, 1.5, 5.5 EntityAlpha CX, 0 heroy = LoadAnimMesh("midia/ninja.b3d",CX) MoveEntity heroy, 0,-5,0 parado = ExtractAnimSeq(heroy,4,4) andando = ExtractAnimSeq(heroy,1,14) anima = 0 camera=CreateCamera(heroy) MoveEntity camera, 0, 20,-20 RotateEntity camera, 20,0,0 light=CreateLight() RotateEntity light, 90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) EntityType cenario, COLIDE_CENARIO rampa = LoadMesh( "midia/escada.3ds" ) EntityType rampa, COLIDE_CENARIO PositionEntity rampa, 9, 0, 18 Collisions COLIDE_HEROI, COLIDE_CENARIO, 2, 3

A cmera ser criada como filha do heri, assim seguir o mesmo pelo cenrio. Veja que tambm fizemos ajustes em sua posio e ngulo para pegar um melhor foco do cenrio.
camera=CreateCamera(heroy) MoveEntity camera, 0, 20,-20 RotateEntity camera, 20,0,0

Carregamos o cenrio e configuramos seu tipo de coliso.


cenario=LoadMesh( "midia/cenariobase.3ds" ) EntityType cenario, COLIDE_CENARIO

Agora falta acionar o sistema de colises. Ligamos as colises do tipo esfera para polgono, pois um cenrio tem que ser sempre polgono (2), seno seria impossvel interagir com ele. Tambm escolhermos o resultado da coliso como deslizar (2).
Collisions COLIDE_HEROI, COLIDE_CENARIO, 2, 2

While Not KeyDown( 1 ) If KeyDown( 205 ) Then TurnEntity CX,0,1,0 If KeyDown( 203 ) Then TurnEntity CX,0, 1,0 If KeyDown( 200 ) MoveEntity CX,0,0, 0.1 If Animate = 0 Then Animate heroy, 1, 0.2, andando Animate = 1 Else Animate heroy, 1, 0.2, parado Animate = 0 EndIf UpdateWorld RenderWorld Text 0,0,"Use as teclas de cursor para andar" Flip Wend End

Quando temos o nosso sistema de colises definido tudo fica mais simples. Para colocar a rampa no cenrio e ativar a sua interao precisamos apenas de 3 linhas de cdigo. Uma para carregar o modelo 3d, outra para posicionar o modelo no local correto e uma para dizer qual o seu grupo de coliso. Como voc se lembra, colises so feitas por grupos de objetos, isso pelos tipos.
rampa = LoadMesh( "midia/escada.3ds" ) PositionEntity rampa, 9, 0, 18 EntityType rampa, COLIDE_CENARIO

A essas alturas est tudo muito lindo, o problema descer a escada. Como no criamos um sistema de gravidade, o objeto s sobe e nunca desce. Gravidade Para criarmos o efeito de gravidade devemos ter uma constante de gravidade e uma varivel para controlar a velocidade atual. A cada iterao do loop, fazemos a velocidade atual ser modificada pela constante de gravidade, pois a gravidade uma acelerao. Quando o objeto se chocar com o cenrio a velocidade zerada. Veja abaixo o exemplo. Exemplo 32
Graphics3D 800,600 SetBuffer BackBuffer() Const COLIDE_HEROI = 1 Const COLIDE_CENARIO = 2 Const G# = 0.05 Global VY# = 0 CX = CreateSphere() ScaleMesh CX, 1.5,5.5,1.5 PositionEntity CX, 0,6,-10 EntityType CX, COLIDE_HEROI EntityRadius CX, 1.5, 5.5 EntityAlpha CX, 0

heroy = LoadAnimMesh("midia/ninja.b3d",CX) MoveEntity heroy, 0,-5,0 parado = ExtractAnimSeq(heroy,4,4) andando = ExtractAnimSeq(heroy,1,14) anima = 0 camera=CreateCamera(heroy) MoveEntity camera, 0, 20,-20 RotateEntity camera, 20,0,0 light=CreateLight() RotateEntity light, 90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) EntityType cenario, COLIDE_CENARIO rampa = LoadMesh( "midia/escada.3ds" ) EntityType rampa, COLIDE_CENARIO PositionEntity rampa, 9, 0, 18 Collisions COLIDE_HEROI, COLIDE_CENARIO, 2, 3 While Not KeyDown( 1 ) If KeyDown( 205 ) Then TurnEntity CX,0,1,0 If KeyDown( 203 ) Then TurnEntity CX,0, 1,0 If KeyDown( 200 ) MoveEntity CX,0,0, 0.1 If Animate = 0 Then Animate heroy, 1, 0.2, andando Animate = 1 Else Animate heroy, 1, 0.2, parado Animate = 0 EndIf VY# = VY# - G# If EntityCollided(CX,COLIDE_CENARIO) Then VY# = 0 MoveEntity CX,0,VY#,0 UpdateWorld RenderWorld Text 0,0,"Use as teclas de cursor para andar" Flip Wend End

Criamos uma constante para gravidade e uma varivel para controlar a velocidade.
Const G# = 0.05 Global VY# = 0

O restante do cdigo dever estar dentro do loop, ou ento em uma funo de fsica invocada pelo loop.
VY# = VY# - G# If EntityCollided(CX,COLIDE_CENARIO) Then VY# = 0 MoveEntity CX,0,VY#,0

Veja que a velocidade atualizada constantemente pela gravidade. Se a entidade se chocar com o cenrio, a velocidade zerada. Devemos sempre colocar um comando MoveEntity para atualizar a posio do personagem. s isso! Simples no? Saltando

Criar um salto em um ambiente 3d muito simples se j existe a funcionalidade de grvida. S precisamos configurar a velocidade y para um valor que corresponda ao esforo inicial do salto. Exemplo 33
Graphics3D 800,600 SetBuffer BackBuffer() Const COLIDE_HEROI = 1 Const COLIDE_CENARIO = 2 Const G# = 0.05 Global VY# = 0 CX = CreateSphere() ScaleMesh CX, 1.5,5.5,1.5 PositionEntity CX, 0,6,-10 EntityType CX, COLIDE_HEROI EntityRadius CX, 1.5, 5.5 EntityAlpha CX, 0 heroy = LoadAnimMesh("midia/ninja.b3d",CX) MoveEntity heroy, 0,-5,0 parado = ExtractAnimSeq(heroy,4,4) andando = ExtractAnimSeq(heroy,1,14) anima = 0 camera=CreateCamera(heroy) MoveEntity camera, 0, 20,-20 RotateEntity camera, 20,0,0 light=CreateLight() RotateEntity light, 90,0,0 cenario=LoadMesh( "midia/cenariobase.3ds" ) EntityType cenario, COLIDE_CENARIO rampa = LoadMesh( "midia/escada.3ds" ) EntityType rampa, COLIDE_CENARIO PositionEntity rampa, 9, 0, 18 Collisions COLIDE_HEROI, COLIDE_CENARIO, 2, 3 While Not KeyDown( 1 ) If KeyDown( 205 ) Then TurnEntity CX,0,1,0 If KeyDown( 203 ) Then TurnEntity CX,0, 1,0 If KeyDown( 200 ) MoveEntity CX,0,0, 0.1 If Animate = 0 Then Animate heroy, 1, 0.2, andando Animate = 1 Else Animate heroy, 1, 0.2, parado Animate = 0 EndIf If KeyDown(57) If VY# = 0 Then VY# = 1 EndIf VY# = VY# - G# If EntityCollided(CX,COLIDE_CENARIO) Then VY# = 0 MoveEntity CX,0,VY#,0 UpdateWorld RenderWorld Text 0,0,"Use as teclas de cursor para andar" Flip Wend End

Apenas adicionamos as linhas abaixo para criar saltos.


If KeyDown(57) If VY# = 0 Then VY# = 1 EndIf

O comando de salto ativado por meio da barra de espaos (57), mas o personagem s saltar se estiver com velocidade vertical igual a 0, isso , se estiver pisando no cenrio. Atirar Boa parte dos jogos 3d fazem uso de algum tipo de arma de fogo. Dessa forma, para se tornar um desenvolvedor de jogos, obrigatoriamente devemos dominar essa tcnica. Existem vrias tcnicas usadas para criar e controlar tiros. A maioria das que j vi usa matrizes, mas isso um erro, pois dificulta a implementao, limita a quantidade de tiros e causa processamento desnecessrio. Usando types voc poder fazer alocao dinmica de recursos e controlar apenas os tiros ativos. A seguir apresentamos a lgica da criao e controle de tiros em um ambiente 3d. 1 PASSO: devemos criar um type modelo para os objetos tiro. Se tivermos apenas um tipo de tiro, teremos apenas um campo para o objeto tiro. Caso tenhamos mais de um tipo, deveremos ter pelo menos mais um campo para sinalizar qual o tipo daquele tiro. 2 PASSO: devemos carregar uma textura para ser aplicada ao objeto de tiro quando esse for disparado. Se tivermos mais de um tipo de tiro, teremos mais texturas. 3 PASSO: devemos escolher uma tecla para disparar um tiro; quando for pressionada invocar a funo criadora de tiros. Tambm devemos colocar dentro do loop a chamada a uma funo de controle de tiros. 4 PASSO: vamos criar a funo construtora de tiros. Devemos pegar a posio atual do personagem que vai disparar o tiro, para que ele aparea no local certo. A segunda tarefa criar uma instncia do Type de tiros. Depois criamos um sprite e o texturizamos. Devemos tambm dar ao objeto a mesma orientao, isso , o mesmo ngulo do atirador, para que o tiro v sempre para frente. Por fim definimos o tipo de coliso do tiro.

5 PASSO: nossa funo de controle. Ela deve ter duas finalidades bsicas: mover o tiro e detectar colises. A partir disso, poderemos gerar eventos a partir das colises, como tirar vida, destruir os tiros, contar pontos, etc. O exemplo a seguir mostra na prtica como criar a funcionalidade de tiros. Exemplo 34
Graphics3D 800,600 SetBuffer BackBuffer() Global COLIDE_HEROI = 1 Global COLIDE_CENARIO = 2 Global COLIDE_TIRO = 3 Type Ttiro Field ob End Type Const G# = 0.05 Global VY# = 0 Global CX = CreateSphere() ScaleMesh CX, 1.5,5.5,1.5 PositionEntity CX, 0,6,-10 EntityType CX, COLIDE_HEROI EntityRadius CX, 1.5, 5.5 EntityAlpha CX, 0 Global heroy = LoadAnimMesh("midia/ninja.b3d",CX) MoveEntity heroy, 0,-5,0 parado = ExtractAnimSeq(heroy,4,4) andando = ExtractAnimSeq(heroy,1,14) anima = 0 camera=CreateCamera(heroy) MoveEntity camera, 0, 20,-20 RotateEntity camera, 20,0,0 light=CreateLight() RotateEntity light, 90,0,0 Global cenario=LoadMesh( "midia/cenariobase.3ds" ) EntityType cenario, COLIDE_CENARIO Global rampa = LoadMesh( "midia/escada.3ds" ) EntityType rampa, COLIDE_CENARIO PositionEntity rampa, 9, 0, 18 Global textiro = LoadTexture("midia\tiro.png",2) Collisions COLIDE_HEROI, COLIDE_CENARIO, 2, 3 Collisions COLIDE_TIRO, COLIDE_CENARIO, 2, 1 While Not KeyDown(1) If KeyDown(205) Then TurnEntity CX,0,1,0 If KeyDown(203) Then TurnEntity CX,0, 1,0 If KeyDown(200) MoveEntity CX,0,0, 0.1 If Animate = 0 Then Animate heroy, 1, 0.2, andando Animate = 1 Else Animate heroy, 1, 0.2, parado Animate = 0 EndIf

If KeyHit(57) Then Atirar() Fisica() VY# = VY# - G# If EntityCollided(CX,COLIDE_CENARIO) Then VY# = 0 MoveEntity CX,0,VY#,0 UpdateWorld RenderWorld Text 0,0,"Use as teclas de cursor para andar" Flip Wend End Function Atirar() x# = EntityX(CX) y# = EntityY(CX) z# = EntityZ(CX) bala.Ttiro = New Ttiro bala\ob = CreateSprite() PositionEntity bala\ob, x#, y#, z# ScaleSprite bala\ob, .2, .2 EntityTexture bala\ob, textiro EntityType bala\ob, COLIDE_TIRO EntityRadius bala\ob, .2, .2 ay# = EntityYaw(CX) RotateEntity bala\ob, 0, ay#, 0 End Function Function Fisica() For this.Ttiro = Each Ttiro MoveEntity this\ob, 0,0,1 If EntityCollided(This\ob,COLIDE_CENARIO) FreeEntity This\ob Delete this EndIf Next End Function

O primeiro passo foi criar um tipo de objetos de coliso para os tiros


Global COLIDE_TIRO = 3

Criamos uma estrutura de Types para os tiros


Type Ttiro Field ob End Type

Carregamos uma textura para os tiros.


Global textiro = LoadTexture("midia\tiro.png",2)

Acionamos o sistema de verificao de colises entre os tiros e o cenrio.


Collisions COLIDE_TIRO, COLIDE_CENARIO, 2, 1

Agora, dentro do loop, quando apertamos a barra de espao, invocamos a funo de disparar tiros.
If KeyHit(57) Then Atirar()

De detro do loop tambm chamamos a funo de fsica, que tambm controla os tiros.
Fisica()

A nossa funo criadora de tiros ficou assim:


Function Atirar() x# = EntityX(CX) y# = EntityY(CX)

z# = EntityZ(CX) bala.Ttiro = New Ttiro bala\ob = CreateSprite() PositionEntity bala\ob, x#, y#, z# ScaleSprite bala\ob, .2, .2 EntityTexture bala\ob, textiro EntityType bala\ob, COLIDE_TIRO EntityRadius bala\ob, .2, .2 ay# = EntityYaw(CX) RotateEntity bala\ob, 0, ay#, 0 End Function

Se ocorrer uma coliso com o cenrio, liberamos o sprite e destrumos o objeto.


If EntityCollided(This\ob,COLIDE_CENARIO) FreeEntity This\ob Delete this EndIf

De inicio, pegamos a posio atual da esfera auxiliar de coliso, afinal ela que controla o jogo.
x# = EntityX(CX) y# = EntityY(CX) z# = EntityZ(CX)

Bem simples no mesmo? Se tivssemos inimigos no cenrio, tambm deveramos ter criado um tipo de entidade inimigo, ativar colises para esse tipo e verificar se elas ocorreram, para mat-los e destruir o tiro. Atirando com o modo pick O pickmode um componente extremamente poderoso do Blitz3d, pois pode nos dar uma srie de informaes e controle sobre entidades 3d e suas estruturas. Por enquanto, o que nos interessa sua capacidade de pegar coisas, isso , de secionarmos um objeto 3d dentro de um cenrio 3d. Podemos usar essa capacidade de pegar entidades para criar um sistema de tiros super rpido, que se comportar de maneira mais realista que o de emisso de projtil. O sistema de tiros que criamos no mdulo anterior pode ser muito interessante para diversos tipos de jogos, onde poder ver o projtil seja algo importante. Mas em jogos de tiro em primeira pessoa isso uma limitao. Quando algum dispara um tiro com uma arma de fogo de verdade, ningum consegue ver o seu projtil se deslocando pelo espao. Por meio do pickmode podemos verificar se uma entidade est na frente da mira quando disparamos um tiro. Se estiver, s nos resta tirar a vida do personagem. Como no necessitamos criar uma entidade e fazer com que ela se desloque pelo cenrio, temos um tiro em tempo real, assim como em jogos do tipo Counter Strike e outros. Nossa primeira aplicao demonstra como funciona o modo de selecionar coisas com o pickmode. So criados vrios polgonos 3d, e ao clicar com o boto direito do mouse sobre algum deles, exibido o nmero de referncia da entidade 3d. Exemplo 35
Graphics3D 640,480,0,2 SetBuffer BackBuffer()

A seguir, criamos o tiro. Veja que o novo tiro colocado na posio extrada do personagem.
bala.Ttiro = New Ttiro bala\ob = CreateSprite() PositionEntity bala\ob, x#, y#, z#

Logo aps texturizamos com a imagem do tiro.


EntityTexture bala\ob, textiro

Depois declaramos a que tipo de objetos de coliso o tiro pertence.


EntityType bala\ob, COLIDE_TIRO

Configuramos o raio da esfera de colises do tiro.


EntityRadius bala\ob, .2, .2

O tiro sempre dever ser dado para frente do atirador, por isso devemos pegar o ngulo y atual do personagem, no nosso caso da esfera criada para auxiliar na coliso do personagem, e passar para o tiro.
ay# = EntityYaw(CX) RotateEntity bala\ob, 0, ay#, 0

Agora nosso tiro est pronto. Toda vez que houver uma iterao do loop de controle do jogo a funo de fsica ser chamada. Vamos conferir o seu cdigo.
Function Fisica() For this.Ttiro = Each Ttiro MoveEntity this\ob, 0,0,1 If EntityCollided(This\ob,COLIDE_CENARIO) FreeEntity This\ob Delete this EndIf Next End Function

Usamos o lao For/Each para passar por todos os objetos ativos do tipo Ttiro.
For this.Ttiro = Each Ttiro

Para cada objeto encontrado, movemos o mesmo 1 unidade de distncia para sua frente.
MoveEntity this\ob, 0,0,1

camera=CreateCamera() PositionEntity camera,0,2,-10 luz = CreateLight() Bola=CreateSphere() EntityPickMode Bola,2 PositionEntity Bola,0,7,0 EntityColor Bola, 255,0,0 Cubo=CreateCube() EntityPickMode Cubo,2 PositionEntity Cubo,0,-1,0 EntityColor Cubo, 0,255,0 Cone=CreateCone() EntityPickMode Cone,2 PositionEntity Cone,5,3,0 EntityColor Cone, 0,0,255 Cil=CreateCylinder() EntityPickMode Cil,2 PositionEntity Cil,-5,3,0 EntityColor Cil, 255,0,255 While Not KeyDown( 1 ) If MouseHit(1)=True Then CameraPick(camera,MouseX(),MouseY()) RenderWorld Text 10,10,"ENTIDADE: " + PickedEntity() Flip Wend End

O comando para pegar um objeto CameraPick( ). Perceba que esse comando disparado quando apertamos o boto esquerdo do mouse:
If MouseHit(1)=True.

Para que esse comando opere, devemos fornecer 3 parmetros para o mesmo: a cmera na qual desejamos usar o comando, a posio x na tela da cmera e a posio y na tela da cmera. Veja que estamos usando a cmera ativa da aplicao cmera e que como coordenadas estamos usando as posies x e y do mouse MouseX(),MouseY(). Ao usarmos a posio atual do mouse, estamos dizendo que vamos selecionar sempre o objeto que estiver sendo apontado pelo mouse, assim o ponteiro do mouse vira um seletor de objetos. Basta clicar com o boto esquerdo dele para selecionar o objeto que estiver sendo apontando. Por fim, vamos descobrir qual objeto est selecionado. A funo PickedEntity() retorna a referncia do objeto que foi selecionado. Assim, para descobrir qual objeto foi clicado, basta invocar a mesma.
Text 10,10,"ENTIDADE: " + PickedEntity()

A primeira coisa a ser feita dizer que a entidade uma entidade que est sobre o controle do pickmode. Assim devemos aplicar o comando EntityPickMode na entidade e dizer como ela deve se comportar.
EntityPickMode Bola,2

Veja que usamos o tipo 2, que para se comportar como polgono; abaixo temos a tabela dos tipos: 0: No pegvel 1: Esfera (usa EntityRadius) 2: Polgono (o formato real da entidade) 3: Caixa (usa o EntityBox como referncia) Como usamos o tipo polgono, cada objeto ser selecionado de acordo com o seu formato real. Vejamos abaixo o comando para pegar um objeto:
If MouseHit(1)=True Then CameraPick(camera,MouseX(),MouseY())

Nosso prximo exemplo mais prtico. Agora que voc j sabe como usar o pickmode, vamos deixar o programa um pouco mais complexo e vamos criar uma situao real de jogo. Nesse exemplo criamos 2 inimigos por meio de types dinmicos e usamos uma mira para servir como referncia de tiro de uma arma. Nesse exemplo voc vai aprender: 1. como criar um sistema de tiros realista. 2. como identificar uma entidade em uma coleo por meio de sua referncia. 3. como automatizar controle de entidades 3d. Exemplo 36
Graphics3D 800,600,16,1 SetBuffer BackBuffer() Global camera=CreateCamera() PositionEntity camera,0,10,-50

luz = CreateLight() Cenario = LoadMesh("midia/cenariobase.3ds") Type Tinimigo Field MODELO Field NOME$ Field VIDA End Type M3D = LoadAnimMesh("midia/zombie.b3d") Inimigo.Tinimigo = New Tinimigo Inimigo\MODELO = M3D EntityPickMode Inimigo\MODELO, 2 Inimigo\NOME$ = "Lucy" Inimigo\VIDA = 5 TranslateEntity Inimigo\MODELO, 10, 0, 0 Inimigo.Tinimigo = New Tinimigo Inimigo\MODELO = CopyMesh(M3D) EntityPickMode Inimigo\MODELO, 2 Inimigo\NOME$ = "Demon" Inimigo\VIDA = 5 TranslateEntity Inimigo\MODELO, -10, 0, 0 Global mira = LoadImage("midia/mira.bmp") Global tiro = LoadSound("midia/tiro.wav") While Not KeyDown( 1 ) Verificar() UpdateWorld RenderWorld Exibir() Flip Wend End Function Verificar() PEGOU=0 If MouseHit(1)=True PlaySound tiro CameraPick(camera,MouseX(),MouseY()) PEGOU = PickedEntity() EndIf For This.Tinimigo = Each Tinimigo If This\MODELO = PEGOU Then This\VIDA = This\VIDA - 1 Next End Function Function Exibir() DrawImage mira, MouseX()-14, MouseY()-14 x = 0 For This.Tinimigo = Each Tinimigo Text 10,10 + x, "NOME: " + This\NOME$ Text 10,25 + x, "VIDA: " + This\VIDA x = x + 40 Next End Function

Abaixo estamos criando um type para ser a estrutura dos nossos inimigos. Estamos reservando um campo para o modelo 3d, um campo para o nome do inimigo e um campo para a vida dele. Perceba que uma entidade inimiga muito mais que um modelo 3d. Um modelo 3d apenas o corpo dela, sendo que um personagem possui vrios dados a serem controlados, por isso a melhor maneira de gerenci-los por meio de types.
Type Tinimigo Field MODELO Field NOME$ Field VIDA End Type

Logo a seguir carregamos um modelo para ser o nosso personagem.


M3D = LoadAnimMesh("midia/zombie.b3d")

A princpio estamos carregando o mesmo em uma varivel para podermos usar a mesma para realizar cpias do modelo.
Inimigo.Tinimigo = New Tinimigo Inimigo\MODELO = M3D EntityPickMode Inimigo\MODELO, 2 Inimigo\NOME$ = "Lucy" Inimigo\VIDA = 5 TranslateEntity Inimigo\MODELO, 10, 0, 0

Ai est o modo padro de criao de um inimigo nesse contexto. Primeiro criamos uma instncia do type:
Inimigo.Tinimigo = New Tinimigo

Depois configuramos o modelo 3d desse personagem. Veja que para o primeiro modelo basta fazer uma simples atribuio. Isso evita que o modelo carregado anteriormente fique perdido no cenrio.
Inimigo\MODELO = M3D

Depois configuramos o modo pick do mesmo para polgono:


EntityPickMode Inimigo\MODELO, 2

Nosso prximo passo dar um nome para ele:


Inimigo\NOME$ = "Lucy"

Vamos destrinchar esse aplicativo?

Vamos configura a vida:


Inimigo\VIDA = 5

Por fim, vamos posicionar o inimigo no local correto:


TranslateEntity Inimigo\MODELO, 10, 0, 0

If This\MODELO = PEGOU Then This\VIDA = This\VIDA - 1 Next End Function

Para criar o segundo modelo usamos praticamente a mesma lgica, mas com uma diferena: no podemos fazer referncia para o mesmo modelo. Essa uma das principais diferenas de um jogo 3d para um jogo 2d do ponto de vista de gerncia de entidades. Enquanto em um jogo 2d precisamos ter apenas uma imagem de cada tipo de entidade, num jogo 3d para cada personagem temos que ter um objeto 3d diferente. A melhor soluo para lidar com isso usar o comando CopyEntity( ), assim no precisaremos carregar vrias vezes o mesmo modelo do disco rgido, pois isso poderia ser bem demorado em jogos com vrios personagens. Veja como foi feito isso para o segundo zumbi:
Inimigo.Tinimigo = New Tinimigo Inimigo\MODELO = CopyMesh(M3D)

Como a funo PickedEntity retorna de forma contnua o ultimo objeto selecionado, ela no pode ser usada diretamente para deteco de tiros, caso contrrio ela criaria uma seqncia ininterrupta de eventos de tirar vida. Para gerenciar isso vamos criar uma varivel de controle. Veja que a mesma sempre ser iniciada na funo com o valor 0.
PEGOU=0

Agora vamos aos eventos disparados quando apertamos o boto esquerdo do mouse;
If MouseHit(1)=True

O primeiro deles emitir um som de tiro:


PlaySound tiro

A seguir disparamos o evento pick, que agora o mesmo que disparar um tiro:
CameraPick(camera,MouseX(),MouseY())

Dentro do nosso loop de jogo deixamos apenas chamadas genricas. No devemos colocar comandos dentro dessa rea, a no ser aqueles essenciais como UpdateWorld, RenderWorld e Flip. Recomendo que todas as outras funcionalidades sejam invocadas a partir de funes. Nesse caso, criamos uma funo de lgica Verificar( ) e uma funo para exibio de dados Exibir( ).
While Not KeyDown( 1 ) Verificar() UpdateWorld RenderWorld Exibir() Flip Wend

E por fim, colocamos o objeto selecionado (o zumbi) na varivel de controle:


PEGOU = PickedEntity()

Como s colocamos um objeto na varivel PEGOU quando o boto do mouse clicado, essa varivel s vai ter contedo no momento que esse boto apertado, pois a cada vez que a funo chamada, essa varivel ser zerada. Assim s ser disparado um nico tiro. Se ao contrrio disso, usssemos a funo PickedEntity diretamente, sempre indicaria que tem um objeto pego, e isso seria o mesmo que dizer que acertou um tiro o tempo todo. Dessa forma tiraria a vida at que ocorresse outro clique do mouse em outro objeto ou ento um clique no vazio. Vamos agora fazer a verificao de qual inimigo foi atingido e tirar 1 ponto de vida.
For This.Tinimigo = Each Tinimigo If This\MODELO = PEGOU Then This\VIDA =

Vamos fazer uma anlise detalhada da funo lgica. Veja a mesma abaixo:
Function Verificar() PEGOU=0 If MouseHit(1)=True PlaySound tiro CameraPick(camera,MouseX(),MouseY()) PEGOU = PickedEntity() EndIf For This.Tinimigo = Each Tinimigo

This\VIDA - 1 Next

Veja que para isso usamos um loop do tipo For-Each. Assim verificamos todas as entidades do tipo Tinimigo. Quando o modelo de uma entidade for igual ao modelo 3d presente na varivel PEGOU, ai ns tiramos a vida dessa entidade. Vamos agora a alguns detalhes da nossa funo de exibio.
DrawImage mira, MouseX()-14, MouseY()-14

Aqui estamos exibindo a mira da arma. Temos duas consideraes importantes a fazer: 1. Exibio de imagens 2d em jogos 3d. 2. Ajuste da imagem. Para exibir uma imagem 2d em um jogo 3d (o que muito usado para criar interfaces grficas) deve-se colocar o comando de exibio depois do comando RenderWorld e Antes do Comando Flip, exatamente no meio deles. Como uma imagem exibida a partir do ponto ordenado pelo comando DrawImage, para que a posio do mouse fique exatamente no meio da imagem devemos fazer uns ajustes. Nesse caso, a imagem usada tem 28 x 28, assim basta dividir a imagem pela metade:
28 / 2 = 14

seguir esse membro e sua animao. Se a mo se mover, a arma se move junto; se rotacionar, rotaciona junto. Assim, podemos carregar vrios objetos declarando-os como filho da mo do personagem. Escondemos todas as armas por meio do comando HideEntity e s mostramos a arma que est sendo usada, por meio do comando ShowEntity. Quando selecionamos uma nova arma, essa receber o comando Show e todas as outras o comando Hide. Como voc se lembra, uma entidade que recebe o comando Hide no renderizada e nem recebe clculos de colises, por isso elas no vo comprometer o processamento, vo apenas ocupa espao de memria. No exemplo abaixo estamos usando um modelo .b3d como bones, ento vamos vincular as armas ao osso da mo. Caso voc use um modelo sem bones, com animao por keyframes, ter que vincular as armas mo ou ao brao. Normalmente modelos animados com bones no possuem partes no corpo, pois so feitos a partir de um nico objeto que sofre extruso. Os modelos com animao por keyframe normalmente so constitudos de diversas partes, pois s podem ser animados por meio de rotao e translao. Vamos ao Exemplo.

E fazer com que o ponto de exibio seja a posio do mouse menos esse metade:
Mousex() 14

Dessa forma a nossa mira ser precisa, pois est centralizada com o mouse. Controle de Armas Imagine um jogo onde existem dezenas de armas diferentes a disposio. Como poderamos controlar cada uma delas para que seus movimentos sigam a lgica de animao dos personagens? Muito simples. Basta que as declaremos como objetos filhos da mo do personagem. Como a arma filha desse membro ela

Exemplo 37
Graphics3D 1280, 1024 SetBuffer BackBuffer() cam = CreateCamera() PositionEntity cam, 0,20,-20 RotateEntity cam, 30,0,0 zumbi = LoadAnimMesh("midia\zombie.b3d") PositionEntity zumbi, 0,-2,0 RotateEntity zumbi, 0, 90, 0 anima = ExtractAnimSeq(zumbi,2,20)

Animate zumbi,1,.2,anima ;PEGANDO O BONE DA MO Mao = FindChild(zumbi,"Joint13") ;ARMA1 bastao = LoadMesh("midia\bastao.3ds", mao) tbastao = LoadTexture("midia\w_bfg.pcx") EntityTexture bastao, tbastao ScaleEntity bastao, .3, .3, .3 MoveEntity bastao, -.5, -1, 1 RotateEntity bastao, 0, -90, 0 HideEntity bastao ;ARMA2 espada = LoadMD2("midia\w_blaster.md2", mao) tespada =LoadTexture("midia\w_blaster.pcx") EntityTexture espada, tespada ScaleEntity espada, .3, .3, .3 MoveEntity espada, -2.5, -2, .5 RotateEntity espada, 0, 180, 0 HideEntity espada ;ARMA3 pistola = LoadMesh("midia\pistol.x", mao) MoveEntity pistola, -.5, -1.5, .5 RotateEntity pistola, -80, 0, 0 ARMA = 3 While Not KeyHit(1) TurnEntity zumbi, 0, 0.1, 0 If KeyHit(57) ARMA = ARMA + 1 If ARMA = 1 ShowEntity bastao HideEntity espada HideEntity pistola EndIf If ARMA = 2 ShowEntity espada HideEntity bastao HideEntity pistola EndIf If ARMA = 3 ShowEntity pistola HideEntity bastao HideEntity espada EndIf If ARMA = 4 ARMA = 0 HideEntity bastao HideEntity espada HideEntity pistola EndIf EndIf UpdateWorld RenderWorld Text 0,0, "PRESSIONE SPACE PARA MUDAR A ARMA" Text 0,20, "ARMA ATUAL: " + ARMA Flip Wend

A primeira coisa que devemos fazer pegar a identidade do bone da mo e guardar em uma varivel. J sabamos previamente qual era o nome desse bone, pois abrimos o modelo no modelador MilkShape3d para verificar isso. Quando voc faz um modelo, voc pode dar nomes a cada malha e a cada bone.
Mao = FindChild(zumbi,"Joint13")

Agora que j temos a identidade do bone da mo, s carregar as armas como filhas desse junta. Veja que colocamos a varivel do bone como segundo parmetro da funo de carregar as armas, para que elas sejam filhas dessa entidade. Como elas so filhas, vo herdar o mesmo comportamento da mo, isso , vo acompanhar a sua animao.
bastao = LoadMesh("midia\bastao.3ds",mao)

Precisamos fazer alguns ajustes na posio da arma para que ela fique perfeitamente encaixada na mo do personagem.
ScaleEntity bastao, .3, .3, .3 MoveEntity bastao, -.5, -1, 1 RotateEntity bastao, 0, -90, 0

Escondemos a arma com o comando hide.


HideEntity bastao

Abaixo temo o sistema de controle das armas dentro do loop do jogo:


If KeyHit(57) ARMA = ARMA + 1 If ARMA = 1 ShowEntity bastao HideEntity espada HideEntity pistola EndIf

Se a tecla space pressionada, incrementamos em uma unidade a varivel de controle de arma atual. Depois verificamos qual a arma ativa. Exibimos a arma ativa e escondemos as outras. Controle do Processo A construo de um jogo 3d deve ser cuidadosamente elaborando, principalmente no quesito performance. Do que vale um jogo que quase ningum pode jogar? Por isso devemos estabelecer meios para gerenciar a demanda de processamento de um jogo para que ele no fuja das especificaes. Duas coisas importantes a gerenciar so a quantidade de polgonos renderizados e o frame rate. Por meio da quantidade de polgonos renderizados, ns podemos controlar a complexidade de um jogo, seus mapas e cenrios, podendo customizar o

Estamos usando como personagem principal o modelo zumbi, disponvel no pacote do MilkShape3D.
zumbi = LoadAnimMesh("midia\zombie.b3d")

mesmo de acordo com as necessidades especificadas. O frame a quantidade de quadros que a enigne consegue renderizar por segundo. Assim, um frame rate de 40 significa que o computador consegue exibir quarenta quadros por segundo. Para que um jogo tenha um efeito de animao suave tem que sustentar um frame rate de no mnimo 25 quadros por segundo. O ideal que essa taxa alcance 50 para que o efeito de animao seja perfeito. O Blitz3D possui um comando interno para informa o nmero de tringulos renderizados, o comando TrisRendered(), mas no possui um comando para frame rate. No exemplo abaixo criamos um algoritmo para informar o frame rate. Pressione a barra de espaos para ir adicionando novos objetos aleatoriamente. Exemplo 38
Graphics3D 800, 600 SetBuffer BackBuffer() Type Tbola Field ob End Type cam = CreateCamera() luz = CreateLight() x = 0 While Not KeyHit(1) If KeyHit(57) px = Rnd(-10,10) py = Rnd(-10,10) pz = Rnd(10, 30) bola.Tbola = New Tbola bola\ob = CreateSphere(32) PositionEntity bola\ob, px, py, pz EntityColor bola\ob, Rnd(0,255), Rnd(0,255), Rnd(0,255) EndIf UpdateWorld RenderWorld Text 0,0, "PRESSIONE SPACE PARA ADICIONAR OBJETOS" Text 0,20,"TRIANGULOS RENDERIZADOS: " + TrisRendered() Text 0,40,"FRAME RATE -> " + FPSReal Flip 0 If Timer + 1000 <= MilliSecs() Timer = MilliSecs() FPSReal = FPSTemp FPSTemp = 0 EndIf FPSTemp = FPSTemp + 1 Wend

O comando Millisecs retorna o tempo do sistema em milisegundos. Mil milisegundos igual a um segundo. A varivel Timer contem uma verificao de milisegundos gravada. Enquanto a nova verificao no for maior que Timer+1000, isso , enquanto no se passar 1 segundo, os dados no sero atualizados.
Timer = MilliSecs()

Caso se passe um segundo, pegamos o tempo atual e colocamos na varivel para atualizar a contagem.
FPSReal = FPSTemp

Pegamos o frame rate da varivel temporria e colocamos na varivel de informao.


FPSTemp = 0

Reiniciamos a varivel contadora de frame rate.


FPSTemp = FPSTemp + 1

O frame rate obtido por simples contador. A cada iterao do loop, uma unidade incrementada. Quando transcorrer um segundo, esse resultado ser transferido para a varivel FPSReal, que agora conter a quantidade de iteraes do loop no ciclo, isso o Frame Rate. Para que o programa possa ter frame rate livre devemos colocar a linha abaixo.
Flip 0

Fra a primeira verificao, cada verificao ser realizada a cada 1 segundo, graas linha abaixo.
If Timer + 1000 <= MilliSecs()

O comando flip serve para atualizar a tela, e quando no damos nenhum valor a ele, sua velocidade ser igual a velocidade de sincronismo da tela do monitor, que e entre 60 e 70. Para deixarmos com velocidade livre, colocamos o parmetro 0. Gostou do programa? Quantos polgonos seu computador suportou dentro da faixa de frame rate 25? O meu chegou a 1.341.184. Mas lgico que meu computador no um padro de mercado de jogos... O ideal que voc teste seus jogos em 3 computadores. Um para baixa performance, um de hardware mediano e um para mquinas de alta performance. Seu jogo tambm dever ter configuraes que permitam ao usurio rodar o jogo pelo menos nessas trs configuraes. SkyDome Em jogos de ambiente fechado existem paredes por todos os lados. Mas em jogos com cenrio em ambientes externos devemos dar um jeitinho para colocar objetos de fundo para representar o cu e nuvens. Normalmente so utilizadas duas tcnicas: skybox e skydome. O skybox uma caixa que texturizada para representar o cu. O

problema do skybox que por ser quadrado no d uma impresso de perfeio. Ele era usado antigamente devido ao baixo poder de processamento das mquinas, mas hoje em dia isso no mais problema. O skydome, ou skyesphere uma esfera que mapeada com uma textura de cu e sofre uma inverso de suas faces. O exemplo abaixo demonstra como criar um skydome.

Para distribuir um jogo comercialmente voc precisa proteger suas mdias para que ningum os utilize indevidamente. Voc pode fazer isso via cdigo ou por meio de ferramentas prprias para isso. Vamos indicar duas boas ferramentas free para isso. Ambas podem ser encontradas no site http://www.blitztools.de.vu. Blitz Media-Linker Essa ferramenta cria um Stand-AloneExecutable, isso , deixa o executvel e as mdias todas em um s arquivo. Tambm d a opo de colocar todos os recursos de mdia em apenas um nico arquivo de dados, assim seu projeto tem apenas um executvel e um arquivo de dados. muito fcil de usar e dispensa explicaes. BBCruncher Esse programa bem mais verstil, possuindo vrias funcionalidade e possvel de ser usando em qualquer programa da famlia Blitz ou at mesmo com o Pure Basic.

Exemplo 39
Graphics3D 640,480 SetBuffer BackBuffer() camera=CreateCamera() luz=CreateLight() sky=CreateSphere() ScaleEntity sky,100,100,100 tex=LoadTexture("midia/sky.bmp") EntityTexture sky, tex FlipMesh sky While Not KeyDown( 1 ) TurnEntity sky, 0, 0.2, 0 RenderWorld Flip Wend End

O primeiro passo foi criar uma esfera e aumentar o tamanho dela.


sky=CreateSphere() ScaleEntity sky,100,100,100

Depois disso, carregamos uma textura que possua uma imagem de cu e aplicamos sobre a esfera.
tex=LoadTexture("midia/sky.bmp") EntityTexture sky, tex

O passo mgico inverter o modelo 3d, fazemos isso com o comando FlipMesh.
FlipMesh sky

Para dar um efeito de maior realismo, ns estamos rotacionando o skydome dentro do loop.
TurnEntity sky, 0, 0.2, 0

Muito fcil! Empacotando o Jogo

Vous aimerez peut-être aussi