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 dual
- tratar o tanque na tela de baixo, ou seja, y+240
- permitir que o tiro ande por todos os 432 pixels
- não desenhar mais o fundo de 16 bits amarelo sujo
- colocar os dois tiled backgrounds
Fonte do programa:
// Includes
#include <PA9.h> // Include for PA_Lib
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"
// Variaveis Globais
s16 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<<8;
s32 y_tiro=-8<<8;
s16 vel_tiro=4;
s8 atirando=0;
void giraturret() {
if (Stylus.Held) {
angulo_turret=PA_GetAngle(x+16,y+16-240,Stylus.X,Stylus.Y);
PA_DualSetRotsetNoZoom(0,angulo_turret);
}
}
void movetanque() {
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<240) { y=240; }
if (y>399) { y=399; }
PA_DualSetRotsetNoZoom(1,angulo_body);
PA_DualSetSpriteXY(0,x,y);
PA_DualSetSpriteXY(1,x,y);
}
}
void atira() {
if (atirando) {
x_tiro+=PA_Cos(angulo_tiro)*vel_tiro;
y_tiro-=PA_Sin(angulo_tiro)*vel_tiro;
PA_DualSetSpriteXY(2,x_tiro>>8,y_tiro>>8);
if (x_tiro<-8<<8 || x_tiro>260<<8 || y_tiro<-8<<8 || y_tiro>440<<8) {
atirando=0;
}
} else {
if (Pad.Newpress.L || Pad.Newpress.R) {
atirando=1;
angulo_tiro=angulo_turret;
x_tiro=(x+12)<<8;
y_tiro=(y+12)<<8;
x_tiro+=PA_Cos(angulo_tiro)*24;
y_tiro-=PA_Sin(angulo_tiro)*24;
PA_DualSetRotsetNoZoom(2,angulo_tiro);
PA_DualSetSpriteXY(2,x_tiro>>8,y_tiro>>8);
}
}
}
// Function: main()
int main(int argc, char ** argv)
{
PA_Init(); // Initializes PA_Lib
PA_InitVBL(); // Initializes a standard VBL
PA_DualLoadSpritePal(0, (void*)tank_turret_Pal);
PA_DualCreateSprite(0, (void*)tank_turret_Sprite, OBJ_SIZE_32X32, 1, 0, x, y);
PA_DualLoadSpritePal(1, (void*)tank_body_Pal);
PA_DualCreateSprite(1, (void*)tank_body_Sprite, OBJ_SIZE_32X32, 1, 0, x, y);
PA_DualLoadSpritePal(2, (void*)tiro_Pal);
PA_DualCreateSprite(2, (void*)tiro_Sprite, OBJ_SIZE_8X8, 1, 0, -8, -8);
PA_DualSetSpriteRotEnable(0, 0);
PA_DualSetSpriteRotEnable(1, 1);
PA_DualSetSpriteRotEnable(2, 2);
PA_EasyBgLoad(0,3,set_bg_1);
PA_EasyBgLoad(1,3,set_bg_2);
// Infinite loop to keep the program running
while (1)
{
giraturret();
movetanque();
atira();
PA_WaitForVBL();
}
return 0;
} // End of main()
Imagens para fazer os fundos:
3 comentários:
ok, então vai ser 1 tiro por vez né?
Tem como você disponibilizar o código fonte tb? Deve estar massa, dando para atirar com o L/R e mirando com a stylus.
Da hora a iniciativa de vocês.. eu poderia ajudar com material tb
Estou programando pra DS também, mas focado em usar o DS com robótica. Eu tava usando a PA_lib, mas dá uns paus locos na lib do Dserial2, um treco q comprei pra conectar no robo.
Sabe aquele demo mais embaixo do aviao??? voce tem o codigo dele?? pq no dserial tem acelerometro, dai daria pra fazer o aviao mudar de posicao soh inclinando o DS.. lol...
qlq coisa me add no msn...
f_odSelot Pat hotmAail dot cMom
tira as letras SPAM.. hehe todo cuidado eh pouco, pricipalmente depois que vi que eh facil detectar emails, inclusive na forma at dot, com expressao regular.. lol
opa voce tem um github ou teria como enviar os codigos
abs
marcelo
Postar um comentário