Ocupando as Duas Telas
Autor: Guilherme - Homebrew Maker | Publicado: 2007-05-06T10:13:00-07:00

Tudo até agora foi programado usando apenas a tela de baixo, a tela 0. Mas este jogo deve ocupar as duas telas do DS. O nosso tanque tem que ficar só na tela de baixo, mas os tiros devem alcançar a tela de cima. Uma maneira de resolver isso seria bastante complexa, colocando os mesmos desenhos dos sprites de baixo nos sprites de cima e ficar controlando para ocultar um sprite em baixo quando ele passa a aparecer em cima.Outra opção seria usar a própria PAlib para fazer esse controle. É o que nós faremos. Todos os comandos de sprites possuem um irmão "Dual", que não precisa especificar qual a tela ele será colocado, o valor de y é que definirá isso. A altura padrão de tela passa a ser 432 pixels (192 pixels da tela de baixo, mais 192 pixels da tela de cima, mais 48 pixels que não mostram imagem porque são o espaço entre as duas telas). O espaço entre as duas tela pode ser alterado pela função PA_SetScreenSpace mas nós continuaremos a usar os 48 pixels pois isso dá uma continuidade bem legal ao tiro.Ah, sim. Faltou falar que os comandos para trabalhar com as duas telas como se fossem uma, são os mesmos comandos de gerenciamento de sprites, somente com a palavra "Dual" na frente (logo após o "PA_") e sem o parâmetro do número da tela.Também iremos colocar os fundos das telas. O fundo set_bg_1.gif vai na tela de baixo e o set_bg_2.gif vai na tela de cima.No programa, as alterações não são muito radicais:trocar os comandos de sprites para os dualtratar o tanque na tela de baixo, ou seja, y+240permitir que o tiro ande por todos os 432 pixelsnão desenhar mais o fundo de 16 bits amarelo sujocolocar os dois tiled backgroundsFonte do programa:// 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;s16 velocidade=1;s16 x=111;s16 y=79+192+48;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;void giraturret() {&nbsp;&nbsp;if (Stylus.Held) {&nbsp;&nbsp;&nbsp;&nbsp;angulo_turret=PA_GetAngle(x+16,y+16-240,Stylus.X,Stylus.Y);&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetRotsetNoZoom(0,angulo_turret);&nbsp;&nbsp;}}void movetanque() {&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;x+=velocidade*(Pad.Held.Right || Pad.Held.A)-velocidade*(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;y+=velocidade*(Pad.Held.Down || Pad.Held.B)-velocidade*(Pad.Held.Up || Pad.Held.X);&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;if (x&lt;0) { x=0; }&nbsp;&nbsp;&nbsp;&nbsp;if (x&gt;223) { x=223; }&nbsp;&nbsp;&nbsp;&nbsp;if (y&lt;240) { y=240; }&nbsp;&nbsp;&nbsp;&nbsp;if (y&gt;399) { y=399; }&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetRotsetNoZoom(1,angulo_body);&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetSpriteXY(0,x,y);&nbsp;&nbsp;&nbsp;&nbsp;PA_DualSetSpriteXY(1,x,y);&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+12)&lt;&lt;8;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y_tiro=(y+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;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, y);&nbsp;&nbsp;PA_DualLoadSpritePal(1, (void*)tank_body_Pal);&nbsp;&nbsp;PA_DualCreateSprite(1, (void*)tank_body_Sprite, OBJ_SIZE_32X32, 1, 0, x, y);&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;// 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()Imagens para fazer os fundos: