segunda-feira, 16 de abril de 2007

Movendo o Tanque


O programa usa os dois sprites abaixo e rotaciona conforme são pressionados os direcionais ou a stylus. Como o programa poderá ser usado por destros e canhotos, eu programei os botões A, B, X e Y para agirem também como se fossem um direcional.




O que o programa faz:
  • Inicia as variáveis.
  • Inicia a PA-Lib, criando um fundo liso com uma cor "amarelo sujo esverdeado"
  • Inicializa os sprites e as rotações
  • Começa o loop infinito
  • Se for usada a stylus, verifica o ângulo entre a stylus e o centro do tanque. Rotaciona o sprite do canhão.
  • Se for feita sacanagem (tipo pressionar esquerda e A), não processa movimento.
  • Se não for pressionado nenhum botão de movimento, também não processa movimento.
  • Se forem pressionados somente botões de movimento horizontal, calcula o movimento horizontal e rotaciona o sprite do tanque.
  • Se forem pressionados somente botões de movimento vertical, processa o movimento vertical e rotaciona o sprite do tanque.
  • Senão (se forem pressionados botões verticais e horizontais), processa os movimentos horizontal e vertical e rotaciona o sprite do tanque.
  • Não deixa o tanque sair da tela.
  • Posiciona os sprites na nova posição calculada.
  • faz os encerramentos de praxe, aguardando o ciclo de frame e voltando ao início do loop infinito.
Código Fonte (desculpem mas não consegui fazer mais otimizado que isso):

// Includes
#include <PA9.h> // Include for PA_Lib
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"

// Function: main()
int main(int argc, char ** argv)
{
  s16 angulo_body=0;
  s16 angulo_turret=0;
  s16 velocidade=1;
  s16 x=111;
  s16 y=79;

  PA_Init(); // Initializes PA_Lib
  PA_InitVBL(); // Initializes a standard VBL
  PA_Init16bitBg(0,0);
  PA_Draw16bitRect(0,0,0,255,191,32768+10*1024+31*32+25);
  PA_LoadSpritePal(0, 0, (void*)tank_turret_Pal);
  PA_CreateSprite(0, 0, (void*)tank_turret_Sprite, OBJ_SIZE_32X32, 1, 0, x, y);
  PA_LoadSpritePal(0, 1, (void*)tank_body_Pal);
  PA_CreateSprite(0, 1, (void*)tank_body_Sprite, OBJ_SIZE_32X32, 1, 0, x, y);
  PA_SetSpriteRotEnable(0, 0, 0);
  PA_SetSpriteRotEnable(0, 1, 1);
  // Infinite loop to keep the program running
  while (1)
  {
    if (Stylus.Held) {
      angulo_turret=PA_GetAngle(x+16,y+16,Stylus.X,Stylus.Y);
      PA_SetRotsetNoZoom(0,0,angulo_turret);
    }
    if ((Pad.Held.Left&&Pad.Held.A) || (Pad.Held.Right&&Pad.Held.Y) || (Pad.Held.Up&&Pad.Held.B) || (Pad.Held.Down&&Pad.Held.X) || (Pad.Held.X&&Pad.Held.B) || (Pad.Held.Y&&Pad.Held.A)) {
      //o usuário está sacaneando, não executa nada
    } else if (!(Pad.Held.Up || Pad.Held.Down || Pad.Held.Left || Pad.Held.Right || Pad.Held.A || Pad.Held.B || Pad.Held.X || Pad.Held.Y)) {
      //nenhuma direção foi pressionada
    } else {
      if ((Pad.Held.Left || Pad.Held.Y || Pad.Held.Right || Pad.Held.A) && !(Pad.Held.Up || Pad.Held.X || Pad.Held.Down || Pad.Held.B)) {
        angulo_body=256*(Pad.Held.Left || Pad.Held.Y);
        x+=velocidade*(Pad.Held.Right || Pad.Held.A) -velocidade*(Pad.Held.Left || Pad.Held.Y);
      } else if (!(Pad.Held.Left || Pad.Held.Y || Pad.Held.Right || Pad.Held.A) && (Pad.Held.Up || Pad.Held.X || Pad.Held.Down || Pad.Held.B)) {
        angulo_body=128*(Pad.Held.Up || Pad.Held.X) +384*(Pad.Held.Down || Pad.Held.B);
        y+=velocidade*(Pad.Held.Down || Pad.Held.B) -velocidade*(Pad.Held.Up || Pad.Held.X);
      } else {
        angulo_body=256*(Pad.Held.Left || Pad.Held.Y);
        x+=velocidade*(Pad.Held.Right || Pad.Held.A) -velocidade*(Pad.Held.Left || Pad.Held.Y);
        if (angulo_body) {
          angulo_body=192*(Pad.Held.Up || Pad.Held.X) +320*(Pad.Held.Down || Pad.Held.B);
        } else {
          angulo_body=64*(Pad.Held.Up || Pad.Held.X) +448*(Pad.Held.Down || Pad.Held.B);
        }
        y+=velocidade*(Pad.Held.Down || Pad.Held.B) -velocidade*(Pad.Held.Up || Pad.Held.X);
      }
      if (x<0) { x=0; }
      if (x>223) { x=223; }
      if (y<0) { y=0; }
      if (y>159) { y=159; }
      PA_SetRotsetNoZoom(0,1,angulo_body);
      PA_SetSpriteXY(0,0,x,y);
      PA_SetSpriteXY(0,1,x,y);
    }
    PA_WaitForVBL();
  }
  return 0;
} // End of main()

4 comentários:

Unknown disse...

Po ficou show de bola. Só achei estranho o corpo do tanque :P.
Mas o movimento está bem dinâmico. Mto legal mesmo.

Leonardo Zimbres disse...

fiz o corpo do tanque em forma de quadrado para simplificar processos de teste de colisão. Quando mais simples, podem fazer jogos mais rápidos.

Leonardo Zimbres disse...

Guilherme, vc pode postar a source? Recomendo o googlepages.

Vou ver se faco uns tanques para servirem de inimigos, no padrao de 32x32.

Guilherme - Homebrew Maker disse...

Postado em
http://www.4shared.com/dir/1725035/b1361591/sharing.html

na pasta
My 4shared/Homebrews/Jogos/Tanques - Combate