Você está na página 1de 10

SubHeaven subheaven.paulo@gmail.

com

Parte 03

Agora vamos colocar movimentos em nossa cena. Vamos tentar colocar um jogo de movimento de cmera e objeto parecido com o jogo World of Warcraft. Pra isso podemos partir de nosso projeto anterior ou criar um novo.

Vamos incluir um GLNavigator (Uma classe que engloba todas a principais rotinas para a movimentao de objetos na cena, facilitando e muito a nossa vida) em nossa cena. Mudar sua propriedade Name para Navegador e a propriedade MovingObject para o nosso MainCubo, indicando assim qual objeto da cena o nosso GLNavigator vai controlar.

Vamos aproveitar e incluir um GLCadencer a cena e ligar sua propriedade Scene ao no GLScene1.

Ao contrario do ultimo tutorial onde no escrevemos nenhum cdigo (S referenciamos uma unit em nosso projeto) esse basicamente pelo velho mtodo. Ento vamos l. Vamos incluir quatro variveis do tipo single (mx1, mx2, my1, my2) no private de nosso projeto. Eles sero usados para capturar a posio do mouse quando o boto esquerdo do mesmo for pressionado e calcular o quando devemos girar a cmera.

Vamos incluir tambm trs constantes. Velocidade ir influenciar a velocidade de movimento de nosso personagem, Angulo influencia a velocidade de giro e DistMax a distncia mxima permitida para a cmera em relao ao personagem.

Vamos comear com o giro de cmera. Vamos selecionar nosso GLSceneViewer e incluir essas linhas no evento OnMouseDown do mesmo: procedure TForm1. GLSceneViewer1MouseDown (Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer); Begin mx1 := x; mx2 := x; my1 := y; my2 := y; end; Estamos, com isso, marcando onde o jogador pressionou o mouse. No evento OnMouseMove do mesmo GLSceneViewer vamos verificar se o boto esquerdo est pressionado e se estiver vamos acompanhar sua posio e ir guardando seu valor em mx2 e my2. procedure TForm1. GLSceneViewer1MouseMove(e(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssLeft in shift then begin mx2 := x; my2 := y; end; end; Agora podemos ir ao evento OnProgress do nosso GLCadencer1 e verificar se houve algum movimento de cmera. Se houver, movimentamos nossa cmera e atualizamos as variveis de controle. Agora vamos selecionar nosso Form1 e vamos ao evento OnMouseWheel do mesmo. Nele vamos verificar se o jogador usa a rodinha do mouse e ajustar a distncia da cmera. procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); var Fator, Distancia: Single; begin Fator := Power(1.1, WheelDelta/120); Distancia := Camera.DistanceTo(MainCubo); if (Fator < 1) or (Distancia <= DistMax) then Camera.AdjustDistanceToTarget(Fator); end; Vamos verificar o que foi feito aqui. Primeiro eu declarei duas varivei do tipo single. Em uma eu calculo qual vai ser o fator de ajuste de cmera (um valor em torno de 0.9 para aproximao e 1.1 para distanciar), eu tambm calculo a distncia entre a cmera e o nosso alvo e guardo na outra varivel. Fator := Power(1.1, WheelDelta/120); Distancia := Camera.DistanceTo(MainCubo); Depois eu verifico duas possibilidades. Se eu tentar afastar a cmera e alcanar o valor de limite eu no posso continuar esse ajuste. if (Fator < 1) or (Distancia <= DistMax) then Camera.AdjustDistanceToTarget(Fator);

Alternativamente eu posso escrever esse if da seguinte forma. if (Fator > 1) and (Distancia > DistMax) then Exit else Camera.AdjustDistanceToTarget(Fator); Se eu estiver tentando afastar a cmera e sua distancia for maior que o limite no fao nada (Comando Exit) seno eu ajusto a cmera. Vamos incluir a unit Keyboard em nosso projeto pois iremos utiliza-la para nossas prximas incluses.

Vamos possibilitar o ajuste de cmera pra quem no tem o Mouse Wheel. Pra isso vamos voltar ao evento OnProgress do GLCadencer e incluir: if IsKeyDown(VK_NEXT) and (Camera.DistanceTo(MainCubo) <= DistMax) then Camera.AdjustDistanceToTarget(1.1); if IsKeyDown(VK_PRIOR) then Camera.AdjustDistanceToTarget(0.9); Com isso eu verifico se as teclas PageUp (VK_PRIOR) ou PageDown (VK_NEXT) esto pressionadas. Se estiverem eu ajusto a distancia com uma taxa padro. Lembre-se de verificar a distncia mxima. Vamos aproveitar que estamos no OnProgress e adicionar as verificaes para movimentar o personagem. Primeiro vamos adicionar duas verificaes: em frente ou pra trs, pois usam o mesmo comando. if IsKeyDown(VK_UP) or IsKeyDown('W') then begin Navegador.MoveForward(-Velocidade); end; if IsKeyDown(VK_DOWN) or IsKeyDown('S') then begin Navegador.MoveForward(Velocidade); end;

Nem h mais segredos aqui. Eu quais teclas estavam pressionadas e chamo o mtodo MoveForward que move nosso Navegador para frente ou para trs de acordo com o valor passado. Agora falta-nos os movimentos para a direita e para a esquerda, e isso resolvemos com mais dois grupos de comandos: if IsKeyDown(VK_LEFT) or IsKeyDown('A') then begin Navegador.TurnHorizontal(-Angulo); end; if IsKeyDown(VK_RIGHT) or IsKeyDown('D') then begin Navegador.TurnHorizontal(Angulo); end; O comando TurnHorizontal apenas gira o objeto horizontalmente. Outro comando til nesse caso tambm seria implementar o comando StrafeHorizontal para andar de lado (No esquecendo que existem ainda os TurnVertical e StrafeVertical). Geralmente em MMORPGs podemos girar e movimentar a cmera livremente, porm ela retorna ao seu ponto inicial a medida que andamos. Ainda no descobri como fazer para ela voltar gradativamente, porm bolei uma maneira de voltar sua posio. Vamos incluir outra cmera na cena e coloca-la tambm como filha de MainCubo. No precisaremos de luz pra ela, Vamos ento setar as propriedades de Position, Up, Direction e TargetObject para ser a mesma da cmera original. Vamos mudar seu Name para Sombra.

Agora vamos criar uma varivel do tipo Boolean para verificar se o boto direito do mouse est pressionado.

Vamos voltar ao evento OnMouseDown do nosso GLSceneViewer e adicionar algumas linhas ao que j tnhamos feito.

procedure TForm1.GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssLeft in shift then begin mx2 := x; my2 := y; Pressionado := true; end else Pressionado := false; end; Com isso ns guardamos o estado do boto esquerdo do mouse pra ser usado em outro evento. Vamos para o OnProgress do GLCadencer e, no bloco onde verificamos as setas do teclado, adicionar a verificao da varivel que carregamos e de acordo com isso resetar a cmera. if IsKeyDown(VK_UP) or IsKeyDown('W') then begin Navegador.MoveForward(-Velocidade); if not Pressionado then Camera.AbsolutePosition := Sombra.AbsolutePosition; end; Trocando em midos, quando o jogador tentar andar com o personagem, n verificamos se o mouse esta pressionado, se no estiver ns resetamos a cmera para a mesma posio da nossa cmera Sombra (Que mantm sempre a mesma posio em relao ao MainCubo). Caso queira, pode incluir esse comando no VK_DOWN. Agora falta apenas ligar algum tipo de gravidade pra o nosso objeto no sair atravessando o mapa ou voando por ele. Como ainda no aprendi a usar os componentes de coliso vamos usar uma sada que encontrei no tutorial do jogo de tiro e achei bem bacana. Vamos incluir a unit VectorGeometry ao nosso projeto.

Voltando pro evento OnProgress do GLCadencer vamos declarar uma varivel do tipo Tvector

E depois vamos incluir essas trs linhas: Vetor := MainCubo.AbsolutePosition; Vetor[1] := Mapa.InterpolatedHeight(Vetor) + 0.5; MainCubo.AbsolutePosition := Vetor; A primeira linha pega a posio atual de nosso MainCubo. Na segunda eu verifico a posio [1] do terreno naquele local e passo esse valor para a posio do MainCubo. Depois disso eu apenas atualizo o MainCubo com a posio j calculada e ajustada. Com isso nosso sistema de movimentao j est parcialmente pronto (Ainda falta adicionar a movimentao pelo mouse e o calculo de percurso para desviar de objetos, mas isso vai ser quando eu descobrir como fazer T_T).