Cenário giratório
periscopando em volta do submarino

O pessoal da velha guarda deve se lembrar, principalmente os "ratos" de fliperama, de uma máquina que vivia cheia de gente, onde era comum esperar horas pela vez de jogar. Um periscópio, uns naviozinhos ao fundo e umas luzes seqüenciais, para simular o torpedo. Lá pelo final dos anos 60, início dos 70.

Em Santos, no litoral de São Paulo, havia uma máquina particularmente especial: gigantesca, envidraçada em três lados, ocupava quase todo o centro do fliper. Disputadíssima, passava a maior parte do tempo "em manutenção". Mas só de olhar para ela a imaginação disparava.

No que se refere a mar e batalha naval, talvez nada supere o máximo em espírito de aventura do que comandar um submarino. Principalmente um daqueles da segunda guerra mundial, quando ainda não contavam com instrumentos sofisticados, mísseis nucleares ou propulsores turbinados.

Na era do computador multimídia, não poderiam faltar os simuladores de submarino. E eles existem, é claro. Mas é certo também que se tornaram tão fiéis à realidade, mas tão fiéis, que se transformaram em jogos chatos. Lembro de ter lido há algum tempo, numa revista inglesa, uma crítica a um desses simuladores. O articulista perguntava porque não havia aquele clássico som do sonar, no jogo.

Os técnicos explicaram então que tal som não existe. Que é uma invenção do cinema, uma criação de hollywood. Mas e daí? Alguém pode, em sã consciência, conceber um submarino sem aquele tradicional "ping"? Uma saída é construirmos o nosso próprio jogo de submarino. Retornar ao velho estilo - naviozinhos passando ao fundo e crau... torpedo! Como fazer?

Toda a estrutura funcional do jogo se baseia num cenário giratório, afinal estamos comandando a ação através do periscópio do submarino. O cenário gira 360 graus e obter isso no Delphi é a maior moleza. Partimos de uma imagem que defini com 1.440 pixels na horizontal por 186 pixels na vertical. Como fiz a imagem? Calma, que isso será tratado em outra parte.

A largura, embora não represente nenhuma mirabolância matemática, equivale a quatro vezes 360, ou seja, cada "direção" teria uma representação de 360 pixels. A razão? Achei que o tamanho ficava legal, em relação à tela do micro. Nada científico, mas os jogos são feitos assim mesmo: sem grandes mágicas compucabalísticas.

Obviamente que estou pensando em um "visor" com essas mesmas medidas: 360 x 186. Assim, num formulário vazio eu crio duas TImage: uma com essas medidas (que chamarei de Tela) e outra com 1440 x 186, que chamarei de Image1 e que deverá ficar com seu atributo Visible em false e deverá conter a imagem do mar.

O controle de movimento do periscópio é feito ao pressionar o botão esquerdo do mouse e movimentando-o para a direita e esquerda. Como a imagem do mar é maior que o visor, teremos, a cada "clicada" e movimento, que determinar a porção do mar que deve ficar à vista. Para isso usaremos uma variável global, chamada Pos (uma integer). Se Pos = 0 então o pedaço (360 pixels) mais à esquerda do mar é mostrado; se Pos = 1439, então o pedaço (360 pixels) mais à direita é mostrado, certo?

Errado. Há um problema aqui, pois se Pos for maior que 1079 (360 x 3 = 1080) então a imagem será formada pelo pedaço que sobrou do mar e mais um pedaço do início da imagem. Claro, se estamos considerando um periscópio que gira livremente os 360 graus. Veja o esboço abaixo:

O truque da programação se resume em verificar se Pos está dentro desta área crítica (acima de 1080) e então proceder à transferência do "pedaço" de cenário para a área do visor. Primeiro criamos um grupo de variáveis globais, para uso deste esquema: Pos e Px, ambas integer (Px é apenas uma variável de controle); Pk como byte (para controle do botão do mouse) e PosMou como TPoint (para guardar as coordenadas originais do mouse, quando o botão é pressionado).

No evento OnMouseDown, da TImage Tela fazemos:

  Pk:= 1; Px:= X; Screen.Cursor:= crNone;
  PosMou:= Mouse.CursorPos;          

No evento OnMouseMove:

  if Pk = 1 then begin
   Pos:= Pos + ((X - Px)*3); Px:= X;
   if Pos < 0 then Pos:= 1440;
   if Pos > 1440 then Pos:= 0;
   MontaTela; Tela.Repaint;
 end;

E no evento OnMouseUp:

  Pk:= 0; Screen.Cursor:= crDefault;
 Mouse.CursorPos:= PosMou;

A montagem da visão foi colocada numa procedure independente para que possamos ir incrementando-a aos poucos. Ei-la:

procedure MontaTela;
var
  T1,T2: HBitmap;
begin
  T1:= Form1.Tela.Canvas.Handle;
  T2:= Form1.Image1.Canvas.Handle;
  if Pos < 1080 then
    BitBlt(T1,0,0,360,186,T2,Pos,0,srccopy)
  else begin
    BitBlt(T1,0,0,1440-Pos,186,T2,Pos,0,srccopy);
    BitBlt(T1,1440-Pos,0,Pos-1080,186,T2,0,0,srccopy);
  end;
end;

Note que a primeira coisa a ser feita é a verificação de Pos. Se ela está dentro da faixa determinada, a impressão da visão é feita numa única operação. Caso contrário, é feita a impressão da primeira parte e depois da segunda parte. Rode o programa e veja como o periscópio funciona perfeitamente. Tudo o que for colocado dentro do cenário, como os navios, trilha dos torpedos, etc, será montado junto com a visão do jogador.

Aí você pergunta: mas é só isso? Sim, basicamente é só isso. O resto é adereço, que a gente inventa para melhorar o jogo e para criar desafios ao jogador. Olhando para a procedure MontaTela conclui-se que a maior parte do trabalho, na criação deste tipo de jogo, fica mesmo por conta dos "gráficos". De fato, este é o grande truque da criação desses joguinhos modernosos: conhecer e praticar a manipulação/edição de imagens. Uma prática que passa a milhas náuticas de distância de profundos conhecimentos de programação, linguagem C e demais cacarecos.

 
online