Publicado por: miwi | junho 6, 2008

[Tutorial] Desenvolvendo para o Nintendo DS, parte IIa – Entradas e Saídas

Outras Partes do Tutorial:

– Parte I: Instalando e Compilando

——————————

Ah, como eu estava com vontade de escrever essa parte do tutorial! Digo, não especificamente ESSA parte, mas estava com vontade de retomar meus estudos da PAlib e a faculdade não estava deixando… A próxima prova é “só” na segunda-feira… eu DEVERIA estar estudando, mas depois de passar o dia inteiro de ontem estudando para a prova de hoje e não ter conseguido dormir mais do que cinco horas, eu resolvi mandar o estudo às favas, só por hoje.

E só até as 18:30, porque às 18:30 eu tenho curso de LabView…

… oi, eu compro tempo, alguém vende?

Desculpem-me pela divagação, voltemos à PAlib… no tutorial de hoje, vamos nos focar nas entradas e saídas mais simples do DS:

  • Saída: texto simples, sem fontes customizadas
  • Entrada: pad (direcional, botões ABXY, botões LR) e stylus

Para a próxima parte do tutorial, nós provavelmente vamos dar uma olhada em saídas mais complexas, já que vocês provavelmente não vão querer apenas fazer programas em modo texto, certo? E, se eu conseguir alguma informação relevante sobre isso até lá, sobre como usar o microfone do DS. A respeito do microfone eu ainda não achei nada mas, eu tenho várias referências aqui, é só questão de eu ter tempo de olhá-las… :p Também deixarei para a próxima parte do tutorial comentários sobre o teclado (fornecido pela PAlib) e o reconhecimento de escrita, também fornecido pela PAlib. Eu até falaria disso aqui hoje, mas a tarde já está acabando e o tutorial já está grande demais mesmo… Ademais, já vai dar para brincar um pouco com o que será visto aqui hoje.

Eu vou tentar explicar tudo do jeito mais simples, e estou tentando fazer tutoriais “light”, para tentar não desencorajar ninguém. Não que eu não pretenda falar sobre coisas mais avançadas, mas o início deve ser bastante simples e claro… por isso, se alguma coisa não ficar clara, perguntem que eu tento responder, ok?

Ao tutorial! o/

SAÍDA: Texto

Existem três tipos de saída de texto (sem contar opções com bordas e fontes customizadas, que serão vistas mais tarde):

  1. Texto Simples
  2. Texto em Caixa
  3. Texto Avançado

Todos os três são bastante simples de serem utilizados, e é justamente por isso que é uma boa idéia começar a estudar a PAlib por eles.

Antes de usar qualquer um deles, porém, você deve inicializar o texto. Como assim? Bom, o DS possui quatro “camadas” de fundo em cada dela, e um desses fundos será utilizado para mostrar texto. Inicializar o texto significa dizer ao DS: olha, eu vou usar texto nessa tela, neste fundo, e depois o DS colocará qualquer texto que você informar nesse fundo sempre que você quiser mostrar texto nessa tela. E como dizer isso para o DS? Com uma simples linha de código:

PA_InitText (bool tela, u8 bg_select)

Onde tela é a tela na qual você quer inicializar o texto (0 para tela inferior, 1 para tela superior) e bg_select é a camada que você quer utilizar, de 0 (para a camada superior) a 3 (para a camada mais inferior).

Uma explicação rápida sobre camadas:

A camada 0 é a camada que está sempre visível, então você provavelmente irá querer colocar o texto nessa camada. Se esse papo de “camadas” está confuso, pense em outras camadas, como as camadas do Photoshop/Gimp, por exemplo: você pode ter várias camadas, e umas ficarão sobre as outras, podendo a que está mais acima ocultar as de baixo. No caso do DS, essa camada mais acima é a 0, e a que está mais ao fundo, a 3.

Inicializado o texto, você pode usar qualquer uma das três funções para mostrar texto na tela.

O primeiro deles você já viu na parte anterior do tutorial, trata-se da função utilizada para mostrar o simpático “Hello World!” na tela. Sua sintaxe é bastante simples – afinal, este É o texto simples:

PA_OutputSimpleText(bool screen, u16 x, u16 y, const char *text)

Novamente, screen é a tela na qual você quer mostrar o texto, e o último argumento é, bem, o texto, que deve ser escrito entre aspas. Mas, e o x e o y? Bom, você precisa dizer onde quer colocar o texto, e informar suas coordenadas parece um bom jeito de fazer isso, certo? Mas, antes que você se apresse em dizer, “poxa, óbvio, né, MiWi?”, eu gostaria de chamar a sua atenção para um detalhe importante. Não é algo muito difícil, mas é algo que você vai usar muito se pretende mexer com programação para o DS: quando você está programando algo para o PC e quer dar as coordenadas fixas de algo, você simplesmente vai lá e informa as coordenadas em pixels, certo?

O DS tem duas telas de 256 x 192 pixels mas, se você tentar colocar algum texto em, digamos (100;100), você não vai conseguir. Por quê? Porque no DS não se posicionam os objetos, sejam eles sprites ou texto, usando os pixels como coordenadas, mas tiles de 8×8 pixels (ao menos, é assim que é feito no PAlib, se você quiser acessar a tela do DS de maneira mais precisa, você provavelmente terá de programar alguma rotina no braço mesmo ;p). Ou seja, o tile (0,0) tem posição (0,0) em pixels, mas o tile (1,1) está na posição (8,8) em pixels.

Se ainda está confuso, veja essas duas imagens (a primeira roubada do blog do Guilherme, a segunda editada por mim):

tela-do-ds-coordenadasTela do DS, com suas coordenadas em pixels

tela-do-ds-tilesTela do DS, com suas coordenadas em tiles.

Como cada tile possui tamanho de 8×8 pixels, é óbvio perceber que converter uma tela de 256×192 pixels resultaria em uma tela de 32×24 tiles, certo?

Dito isso, acho que agora ficou mais simples visualizar como funcionam as coordenadas X e Y na PAlib, certo?

Então, voltando à sintaxe do texto simples:

PA_OutputSimpleText(tela, x, y, texto)

Para escrever um “Hello World” na tela superior, mais ou menos na metade da tela, nós deveríamos algo como:

PA_OutputSimpleText(1, 15, 11, “Hello World”)

A sintaxe dessa função é a mais simples possível, mas foi bom para mostrar alguns conceitos básicos da PAlib/DS, como tiles e camadas 🙂

Mas, e se você quiser mostrar texto numa parte determinada da tela? Como nessa função você apenas define o local de início do texto, se você informar um texto muito longo ele vai para a próxima linha e continua… mas e se você quiser que o texto fique apenas na metade da tela, por exemplo?

Aí entra outra função de texto, o texto em caixa, cuja sintaxe é essa:

PA_BoxText( tela, x_base, y_base, x_máximo, y_máximo, texto, limite)

Tela e texto não precisam de explicação, creio eu. As duas coordenadas x (x_base e x_máximo) e as duas coordenadas y (y_base e y_máximo) delimitam o tamanho da sua caixa. As coordenadas de base se referem às coordenadas do lado superior esquerdo da caixa, e as coordenadas de máximo se referem às coordenadas do lado inferior direito da caixa. Por exemplo, para ter seu texto dentro de uma caixa que ocupe a metade esquerda da tela superior, você teria algo assim:

PA_BoxText( 1, 0, 0, 15, 23, “Insira um texto realmente grande dessa caixa para mostrar que ele so ira aparecer na metade da tela” , limite)

Só falta descobrir o que é aquele limite, certo? O limite é o número máximo de caracteres que irão aparecer em um dado momento. Se você for escrever um texto grande na tela, é bom verificar com uma função simples qual o número máximo de caracteres que podem ser mostrados, porque se você tentar mostrar mais caracteres do que o que cabe na sua caixa, o resultado não será o esperado. Um exemplo para calcular o número máximo de caracteres seria esse:


u8 maxChar = (maxx - basex)*(maxy - basey);

O limite também pode ser usado para criar aquele efeito “uma letra por vez”, como se uma máquina de escrever estivesse escrevendo aquelas palavras na tela, pouco a pouco. Para isso, basta criar um loop que, a cada iteração aumente o limite em um, até que o texto ou o tamanho da caixa cheguem ao final. Assim, a cada iteração o texto mostrado será um caractere maior, o que irá causar a impressão de máquina de escrever. Um exemplo disso pode ser encontrado na pasta de exemplos da PAlib, em Text/BoxText.

O código é este aqui, com comentários traduzidos:


/* Desta vez, imprima o texto letra por letra...
*/

// Includes
#include        // Include para a PA_Lib

char text[200]; //Este será o nosso texto

// Função: main()
int main(int argc, char ** argv)
{
PA_Init();    // Inicializa a PA_Lib
PA_InitVBL(); // Initicializa a VBL

//Inicializa o sistema de texto na tela inferior
PA_InitText(0, // Tela de baixo
0);      // Camada superior
PA_InitText(1, 0);  // Inicializa o sistema de texto na tela superior
u32 nletters = 0; //número de letras a serem mostradas
u32 letter = 0; // letra atual sendo escrita

while (letter == nletters){

// Faça isso até o texto ser todo escrito na tela

++nletters;
//Próximo frame, mais uma letra a ser mostrada...

/* Essa função escreve um número pré-determinado de letras,
desta maneira parece que você está digitando na tela ! */
letter = PA_BoxText(1, 2, 2, 29, 15,
"Hi there :p  Cool, the function works perfectly !
So you see the text being typed...
\n Line break works...", nletters);

/*letter é a variável que recebe o número de caracteres escrito
pela função. Quando esse número for diferente do limite,
significa que o texto acabou (ou, se você colocou uma
função para verificar os limites da caixa, que
o limite da caixa foi atingido) */
PA_WaitForVBL();

/*Você pode aumentar o número de WaitForVBL se quiser
que o texto apareça mais lentamente */
}

PA_OutputSimpleText(0, 10, 10, "Terminou !"); // Terminado...

// Loop infinito para que o programa continue rodando
while (1){

PA_WaitForVBL();

}

return 0;
} //Fim do main()

Bom, agora que o texto em caixa já está bem explicado, falta apenas o texto avançado. Mas, não precisa se assustar com o nome! Quem já programou já deve estar acostumado com isso (ou não, já que algumas linguagens não funcionam assim…): você escreve o texto e, dentro do texto, coloca “marcadores”, que irão ser substituídos pelos argumentos que vem depois dele. Opa, esquisito? Sem problemas, vamos dar uma olhada na sintaxe:

PA_OutputText(bool screen, u16 x, u16 y, const char *text, arguments…)

Ou seja, praticamente igual ao texto simples… com exceção daqueles argumentos ali no final. Como já dito, você irá escrever um texto qualquer e, em algum lugar do texto, você irá adicionar marcadores que serão substituídos pelos argumentos passados (que são nomes de variáveis). Para que serve isso? Para mostrar um texto que contenha o nome do jogador ou o seu número de pontos, por exemplo. Os marcadores mais simples são esses:

  • %d: para inteiros
  • %f.X : para números reais não-inteiros, onde X é o número de casas depois da vírgula que você deseja mostrar
  • %s : texto, como o nome do jogador, por exemplo.

Um detalhe sobre o %s: você pode criar um texto assim, por exemplo:


char name[10] = "Mollusk";
PA_OutputText(1,0,0,"Hi %s", name);

/*Irá aparecer "Hi Mollusk", já que o %s será substituído pelo

conteúdo da variável name */

Porém, se você for adicionando caracteres a uma variável do tipo char[] (em C, textos são considerados cadeias de caracteres, por isso são definidos como vetores do tipo char, onde cada posição é ocupada por um caractere) é importante que o último caractere seja 0 (zero), para que o programa “saiba” que o seu texto terminou ali.

E… só, é só isso sobre textos. Mas, você ainda pode… mudar a cor do seu texto! Para deixá-lo mais gay personalizado, por exemplo. Existem três maneiras de fazer isso:

  • PA_SetTextCol(screen, r, g, b) – muda a cor de TODO o texto na tela selecionada, mesmo o que já havia sido escrito quando a função foi chamada. r,g,b são os valores da quantidade de vermelho, verde e azul (red, green, blue – r,g,b) da cor, de 0 a 31: vermelho é 31,0,0, verde seria 0,31,0 e azul seria 0,0,31, por exemplo. E cinza é 22, 22, 22 e rosa é 31,0,31.
  • PA_SetTextTileCol(screen, i); – muda a cor do texto que for escrito na tela DEPOIS dessa função ter sido chamada, para uma cor i, que pode variar de 0 a 9 ((0 = branco, 1 = vermelho, 2 = verde, 3 = azul, 4 = roxo, 5 = ciano, 6 = amarelo, 7 = cinza claro, 8 = cinza escuro, 9 = preto)
  • %cX – muda a cor de apenas um trecho de uma String, onde X é a cor de 0 a 9 (vale a mesma lista do item anterior). Isso é bom para quando você quer um texto de múltiplas cores, como: PA_OutputText(0, 0, 0, “Color test…%c1another one, %c2again, %c3again…”);

Sobre a parte de texto, seria isso. É claro que ainda falta ver coisas mais complexas como mudar a fonte e colocar borda mas, deixemos isso para a próxima parte ;p

ENTRADA: Pad e Stylus

Olha, eu preciso dizer… você talvez fique chocado com a facilidade de receber entradas do usuário via PAD e Stylus no DS. A PAlib tem funções muito, muito úteis para lidar com os comandos feitos pelo jogador. Sério.

Para o PAD, você possui a seguinte estrutura para cada botão:

PAD.TipoDeInteração.Botão, sendo que isto pode estar em 0 (falso) ou 1 (verdadeiro) para cada TipoDeInteração.Botão.

Esquisito? OK, vamos ver os tipos de interação, então:

  • Newpress é quando você acabou de pressionar a tecla, ele fica em um por apenas um frame
  • Held é, por padrão, iguala 0, e passa a 1 quando um botão está sendo pressionado.
  • Released quando um botão é solto (foi pressionado mas não está mais sendo pressionado…), fica em 1 por um único frame.

E os nomes de cada botão:

  • Left, Right, Down e Up para os direcionais
  • A,B,X,Y para as teclas ABXY
  • L e R para os botões L e R
  • Start e select para… start e select…

Então, digamos que você queira ver se a tecla R está sendo pressionada. Você poderia fazer algo como:


if (Pad.Held.R)

{

/*escreva o que você que aconteça quando o

jogador manter R pressionado aqui */

}

Ou, se você quer verificar se o usuário apertou o botão A no momento certo para dar um combo, por exemplo:


while (tempoAtual <= tempoMaximo)

/* enquanto o tempo atual for menor do que

o tempo máximo permitido para ocorrer o combo, verifique se

o jogador apertou A */

{

if (Pad.NewPress.A)

{

/*Combo!*/

}

tempoAtual++;

PA_WaitForVBL();

}

E o mesmo serve para a interação Released e para todos os tipos de botões. Eu falei que era simples, não falei?

Para a Stylus, não muda muita coisa: existem os mesmos tipos de interação vistos para o PAD, só que sem a necessidade de indicar mais algum parâmetro, já que, bom, existe apenas a Stylus, e existem também as variáveis X e Y que… indicam as coordenadas X e Y da Stylus sobre a tela. (novamente, X e Y em Tiles!)

Por exemplo, pra escrever as coordenadas de X e Y sob a caneta, você poderia ter algo assim:

if (Stylus.Held)

{

PA_OutputText( 0, Stylus.X, Stylus.Y, "(%d,%d)",Stylus.X, Stylus.Y);

}

Se você trocar a tela 0 pela 1, por exemplo, você pode interagir no mesmo ponto em que você tocou na tela de baixo, na tela de cima.

E… por hoje é só =D Ainda faltam as saídas mais complexas e, outras entradas, mas uma coisa de cada vez, certo? ;D Acho que já dá para criar alguma coisa com isso. Eu ia colocar algum exemplo mais completo, mas eu estou super cansada, então fica para a próxima =/

Mas, os exemplos que vem junto com a PAlib são muito bons (simples, claros e bem comentados :), então dê uma olhada neles que você provavelmente terá mais idéias de como usar o hardware do DS para fazer algo legal. Especialmente as pastas Text e Input/Pad e Input/Stylus, que foi o que nós vimos hoje.

Espero que vocês estejam gostando. Se não estiverem, eu páro porque dá um trabalhão escrever tudo isso xD Agradecimento especial ao Rafael Lima, que foi me deixar um scrap motivador hoje,… 🙂

Anúncios

Responses

  1. […] [Tutorial] Desenvolvendo para o Nintendo DS, parte IIa – Entradas e Saídas […]

  2. man.. vc é o cara… to aprendendo um pouco de C.. e qro aprender a programar alguma pra nds… abraço e espero q continue postando

  3. Olá. Legal vou ver se ainda vou programar para outras arquiteturas, gosto de games, mas sempre prefiro joga-los! XD

    Vamos ver se um dia produzo algum…

    Até mais.

  4. Wow, post gigante sobre programação.

    Atualmente passo longe, mas se eu decidir fazer algo pra DS juro que leio tudo que você publicar por aqui.

    o/

  5. Eu estou gostando 😀
    Apesar de eu estar um pouco sem tempo para poder testar isso tudo aí xD
    E provavelmente se eu tentar irei apanhar feio ^^
    Mas eu juro que um dia vou tentar xP

    Quando eu crescer quero manjar de programação igual a Miwi 😀

  6. “/*Você pode aumentar o número de WaitForVBL se quiser
    que o texto apareça mais lentamente */”
    Nesta parte vc qis diz q devemos por mais deste code pra retardarmos o processo ou q devemos por um número entre os parênteses, como parâmetro?

    PS: Mto bom este post..Vc e o Guilherme estão me sendo de grande ajuda msmo em vista q qero fazer um fangame do MegaMan pro DS.


Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

Categorias

%d blogueiros gostam disto: