Vetores
Autor: Guilherme - Homebrew Maker | Publicado: 2007-05-29T18:12:00-07:00

Vetores são como variáveis, mas podem conter diversos valores. Digamos, por exemplo, que eu queira trabalhar com moedas. Cada tipo de moeda tem um valor (em centavos): moeda1=1, moeda2=5, moeda3=10, moeda4=25, moeda5=50 e moeda6=100. Usando as variáveis dessa forma, se eu quisesse usar um for para mostrar o valor de todas as moedas, eu não conseguiria.O vetor vem ao meu socorro. Por exemplo:s16 moeda[6]={1,5,10,25,50,100};for (i=0; i&lt;6; i++) {&nbsp;&nbsp;PA_OutputText(0,0,i,"moeda[%d]=%d",i,moeda[i]);} O código acima apresentará uma saída asim:moeda[0]=1moeda[1]=5moeda[2]=10moeda[3]=25moeda[4]=50moeda[5]=100Nós fizemos um vetor de 6 posições (de 0 a 5) contendo os valores das moedas do Brasil.Vamos aplicar isso ao nosso jogo. O cenário tem áreas de areia, de terra, de grama e de água. O tanque não deve andar sobre a água. Mas o tipo de solo também influencia na velocidade do tanque. Então faremos o tanque andar na metade da velocidade na areia (1 pixel a cada 2 frames), em velocidade normal na grama (1 pixel por frame) e em velocidade dobrada na terra (2 pixels por frame). Usando a lógica de bit shifting que já estudamos, teríamos uma tabela contendo velocidade=0 se o terreno for água, 128 se for areia, 256 se for grama e 512 se for terra.Eu dividi o background em quadrados de 16x16 pixels e coloquei num vetor. Como a imagem tem 256x192 pixels, isso divindo por 16 cada valor me gerou um vetor de 192 posições (16x12=192). O vetor é representado de forma linear, mas a tela tem linhas e colunas.  Então é necessária uma fórmula para acessarmos todas as posições. Essa fórmula é: linha*largura+coluna. Neste caso é linha*16+coluna. A posição de linha e coluna é calculada relativamente ao centro do tanque para facilitar a programação.Como existe a possibilidade de ter áreas onde o tanque não se move, ele jamais deve entrar com o centro nessas áreas. Quando ele entrar em uma área de velocidade 0, a posição do tanque deve ser restaurada para posição antiga, anterior à entrada nessa área. Se o tanque entrasse numa área de velocidade 0, ele jamais sairia dela, pois a sua velocidade seria 0.Outra coisa que corrigi é que quando o tanque atingia uma borda da tela e o controle estivesse sendo pressionado na diagonal, o tanque continuava se movendo em apenas um dos eixos ao invés de parar. Agora ele pára.Vamos ao código-fonte. Analisem o fonte e encontrem o que foi falado acima. Se houver alguma dúvida, façam a pergunta nos comentários.// Includes#include &lt;PA9.h&gt;       // Include for PA_Lib#include &quot;gfx/all_gfx.c&quot;#include &quot;gfx/all_gfx.h&quot;// Variaveis Globaiss16 angulo_body=0;s16 angulo_turret=0;s32 x=111&lt;&lt;8;s32 y=(79+192+48)&lt;&lt;8;s16 angulo_tiro=0;s32 x_tiro=-8&lt;&lt;8;s32 y_tiro=-8&lt;&lt;8;s16 vel_tiro=4;s8 atirando=0;s16 vel_terra[192]={0,128,128,256,256,256,256,256,256,256,256,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,512,512,512,512,512,512,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,512,512,512,512,512,512,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,512,512,512,512,512,512,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,512,512,512,512,512,512,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,256,256,256,256,256,256,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,256,256,256,256,256,256,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,256,256,256,256,256,256,256,256,128,128,0,&nbsp;&nbsp;0,128,128,256,256,256,256,256,256,256,256,256,256,128,128,0,&nbsp;&nbsp;0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,&nbsp;&nbsp;0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,&nbsp;&nbsp;0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};void giraturret() {&nbsp;&nbsp;if (Stylus.Held) {&nbsp;&nbsp;&nbsp;&nbsp;angulo_turret=PA_GetAngle((x&gt;&gt;8)+16,(y&gt;&gt;8)+16-240,Stylus.X,Stylus.Y);&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetRotsetNoZoom(0,angulo_turret);&nbsp;&nbsp;}}void movetanque() {&nbsp;&nbsp;s16 centro_x=((x&gt;&gt;8)+15)&gt;&gt;4;&nbsp;&nbsp;s16 centro_y=((y&gt;&gt;8)-240+15)&gt;&gt;4;&nbsp;&nbsp;s16 tipoterra=0;&nbsp;&nbsp;s16 velocidade=0;&nbsp;&nbsp;s32 xvelho=x;&nbsp;&nbsp;s32 yvelho=y;&nbsp;&nbsp;if (centro_x&lt;0||centro_x&gt;15||centro_y&lt;0||centro_y&gt;11) {&nbsp;&nbsp;&nbsp;&nbsp;tipoterra=0;&nbsp;&nbsp;&nbsp;&nbsp;velocidade=0;&nbsp;&nbsp;} else {&nbsp;&nbsp;&nbsp;&nbsp;tipoterra=centro_y*16+centro_x;&nbsp;&nbsp;&nbsp;&nbsp;velocidade=vel_terra[tipoterra];&nbsp;&nbsp;}&nbsp;&nbsp;if ((Pad.Held.Left &amp;&amp; Pad.Held.A) || (Pad.Held.Right &amp;&amp; Pad.Held.Y) || (Pad.Held.Up &amp;&amp; Pad.Held.B) || (Pad.Held.Down &amp;&amp; Pad.Held.X) || (Pad.Held.X &amp;&amp; Pad.Held.B) || (Pad.Held.Y &amp;&amp; Pad.Held.A)) {&nbsp;&nbsp;  //o usu&aacute;rio est&aacute; sacaneando, n&atilde;o executa nada&nbsp;&nbsp;} 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)) {&nbsp;&nbsp;  //nenhuma dire&ccedil;&atilde;o foi pressionada&nbsp;&nbsp;} else {&nbsp;&nbsp;&nbsp;&nbsp;if ((Pad.Held.Left || Pad.Held.Y || Pad.Held.Right || Pad.Held.A) &amp;&amp; !(Pad.Held.Up || Pad.Held.X || Pad.Held.Down || Pad.Held.B)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angulo_body=256*(Pad.Held.Left || Pad.Held.Y);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x+=velocidade*(Pad.Held.Right || Pad.Held.A)-velocidade*(Pad.Held.Left || Pad.Held.Y);&nbsp;&nbsp;&nbsp;&nbsp;} else if (!(Pad.Held.Left || Pad.Held.Y || Pad.Held.Right || Pad.Held.A) &amp;&amp; (Pad.Held.Up || Pad.Held.X || Pad.Held.Down || Pad.Held.B)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angulo_body=128*(Pad.Held.Up || Pad.Held.X)+384*(Pad.Held.Down || Pad.Held.B);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y+=velocidade*(Pad.Held.Down || Pad.Held.B)-velocidade*(Pad.Held.Up || Pad.Held.X);&nbsp;&nbsp;&nbsp;&nbsp;} else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angulo_body=256*(Pad.Held.Left || Pad.Held.Y);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (angulo_body) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angulo_body=192*(Pad.Held.Up || Pad.Held.X)+320*(Pad.Held.Down || Pad.Held.B);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angulo_body=64*(Pad.Held.Up || Pad.Held.X)+448*(Pad.Held.Down || Pad.Held.B);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x+=velocidade*(Pad.Held.Right || Pad.Held.A)-velocidade*(Pad.Held.Left || Pad.Held.Y);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y+=velocidade*(Pad.Held.Down || Pad.Held.B)-velocidade*(Pad.Held.Up || Pad.Held.X);&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;centro_x=((x&gt;&gt;8)+15)&gt;&gt;4;&nbsp;&nbsp;&nbsp;&nbsp;centro_y=((y&gt;&gt;8)-240+15)&gt;&gt;4;&nbsp;&nbsp;&nbsp;&nbsp;if (centro_x&lt;0||centro_x&gt;15||centro_y&lt;0||centro_y&gt;11) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tipoterra=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;velocidade=0;&nbsp;&nbsp;&nbsp;&nbsp;} else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tipoterra=centro_y*16+centro_x;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;velocidade=vel_terra[tipoterra];&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;if (velocidade==0 || x&lt;0 || x&gt;57088 || y&lt;61440 || y&gt;102144) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x=xvelho;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y=yvelho;&nbsp;&nbsp;&nbsp;&nbsp;}//&nbsp;&nbsp;&nbsp;&nbsp;if (x&lt;0) { x=0; }//&nbsp;&nbsp;&nbsp;&nbsp;if (x&gt;57088) { x=57088; }//&nbsp;&nbsp;&nbsp;&nbsp;if (y&lt;61440) { y=61440; }//&nbsp;&nbsp;&nbsp;&nbsp;if (y&gt;102144) { y=102144; }&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetRotsetNoZoom(1,angulo_body);&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetSpriteXY(0,x&gt;&gt;8,y&gt;&gt;8);&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetSpriteXY(1,x&gt;&gt;8,y&gt;&gt;8);&nbsp;&nbsp;}}void atira() {&nbsp;&nbsp;if (atirando) {&nbsp;&nbsp;&nbsp;&nbsp;x_tiro+=PA_Cos(angulo_tiro)*vel_tiro;&nbsp;&nbsp;&nbsp;&nbsp;y_tiro-=PA_Sin(angulo_tiro)*vel_tiro;&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetSpriteXY(2,x_tiro&gt;&gt;8,y_tiro&gt;&gt;8);&nbsp;&nbsp;&nbsp;&nbsp;if (x_tiro&lt;-8&lt;&lt;8 || x_tiro&gt;260&lt;&lt;8 || y_tiro&lt;-8&lt;&lt;8 || y_tiro&gt;440&lt;&lt;8) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atirando=0;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;} else {&nbsp;&nbsp;&nbsp;&nbsp;if (Pad.Newpress.L || Pad.Newpress.R) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atirando=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;angulo_tiro=angulo_turret;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x_tiro=((x&gt;&gt;8)+12)&lt;&lt;8;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y_tiro=((y&gt;&gt;8)+12)&lt;&lt;8;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x_tiro+=PA_Cos(angulo_tiro)*24;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y_tiro-=PA_Sin(angulo_tiro)*24;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetRotsetNoZoom(2,angulo_tiro);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetSpriteXY(2,x_tiro&gt;&gt;8,y_tiro&gt;&gt;8);&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;}}// Function: main()int main(int argc, char ** argv){&nbsp;&nbsp;&nbsp;&nbsp;PA_Init();    // Initializes PA_Lib&nbsp;&nbsp;PA_InitVBL(); // Initializes a standard VBL&nbsp;&nbsp;PA_DualLoadSpritePal( 0, (void*)tank_turret_Pal);&nbsp;&nbsp;PA_DualCreateSprite( 0, (void*)tank_turret_Sprite, OBJ_SIZE_32X32, 1, 0, x&gt;&gt;8, y&gt;&gt;8);&nbsp;&nbsp;PA_DualLoadSpritePal( 1, (void*)tank_body_Pal);&nbsp;&nbsp;PA_DualCreateSprite( 1, (void*)tank_body_Sprite, OBJ_SIZE_32X32, 1, 0, x&gt;&gt;8, y&gt;&gt;8);&nbsp;&nbsp;PA_DualLoadSpritePal( 2, (void*)tiro_Pal);&nbsp;&nbsp;PA_DualCreateSprite( 2, (void*)tiro_Sprite, OBJ_SIZE_8X8, 1, 0, -8, -8);&nbsp;&nbsp;PA_DualSetSpriteRotEnable( 0, 0);&nbsp;&nbsp;PA_DualSetSpriteRotEnable( 1, 1);&nbsp;&nbsp;PA_DualSetSpriteRotEnable( 2, 2);&nbsp;&nbsp;PA_EasyBgLoad(0,3,set_bg_1);&nbsp;&nbsp;PA_EasyBgLoad(1,3,set_bg_2);&nbsp;&nbsp;PA_InitText(1,0);&nbsp;&nbsp;PA_SetTextCol(1,31,31,31); &nbsp;&nbsp;// Infinite loop to keep the program running&nbsp;&nbsp;while (1)&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;giraturret();&nbsp;&nbsp;&nbsp;&nbsp;movetanque();&nbsp;&nbsp;&nbsp;&nbsp;atira();&nbsp;&nbsp;&nbsp;&nbsp;PA_WaitForVBL();&nbsp;&nbsp;}&nbsp;&nbsp;return 0;} // End of main()