Jour 2 - Apprentissage du C ← Précédent
Le seul système de sortie dont nous parlerons pour le moment est le système basique de wifi avec un serveur et de connexion sur un serveur DNS pour ouvrir une page PHP de texte... Ensuite, nous verrons les différentes méthodes d’entrée : le pad, stylet, et clavier...
Le texte est une partie importante des jeux DS. Imaginez un jeu sans dialogue ou instructions...Par contre, créer vos propres fonctions de texte serait difficile, et c’est justement là qu’intervient la PAlib. Elle contient pas mal de fonctions texte bien pratiques.
Pour initialiser le texte, utilisez PA_InitText (bool screen, u8 bg_select)
Le premier argument correspond à l’écran (1 = haut, 0 = bas), et le second au fond (0-3). Désormais, pour toute fonction texte utilisant le même écran, le même fond sera utilisé.
La création de texte simple est facile, sinon on ne parlerait pas de texte simple. Utilisez PA_OutputSimpleText(bool screen, u16 x, u16 y, const char *text). L’argument screen correspond à l’écran à utiliser. x correspond à la coordonnée x, en tiles(0-31). y quant à lui correspond à la coordonnée y, en tiles(0-23). text correspond bien évidemment au texte.
Voici un exemple de code...
void printText() { PA_InitText(1,0); PA_SetTextCol(1,31,31,31); PA_OutputSimpleText(1,0,0,"Ceci est un exemple"); }
Si vous voulez effacer du texte, réecrivez dessus avec des espaces, par exemple :
PA_OutputSimpleText(1, 0, 0, " ");
Le texte simple peut s’avérer utile, mais souvent ça ne suffit pas. Des fois vous avez besoin de texte, confiné à une portion rectangulaire de l’écran. C’est le but de PA_BoxText(). Voici les arguments:
Cette fonction retourne le nombre de lettres affichées actuellement.
Si vous avez du texte tapé lentement, augmentez simplement la limite par 1. Lorsque le numéro retourné ne change pas, il s’est arrêté (soit parce qu’il n’y a plus de texte, soit parce que la limite a été atteinte). A ce moment, vous pouvez arrêter d’augmenter la limite.
Si votre texte est long, vous devez connaître le nombre maximum de caractères pouvant être affichés. Dans ce cas, utilisez cette formule...
u8 maxChar = (maxx - basex)*(maxy - basey);
Ca devrait marcher
.
Maintenant que vous avez vu comment imprimer des textes basiques à l’écran, nous allons voir ce qui pourrait être considéré comme la fonction texte la plus importante : PA_OutputText(bool screen, u16 x, u16 y, const char *text, arguments...). Comme vous pouvez le voir, elle n’est pas si différente de la première fonction texte, à l’exception de sa liste d’arguments, qui est très importante. Elle autorise l’affichage du contenu de variables ou de chaines de caractères directement sur l’écran, ce qui se révèle très pratique pour le debugging !
Vous pouvez jeter un coup d’oeil à l’exemple de Text/Text pour quelques applications...
Remarque importante : Si vous êtes familier avec les options avancées de printf (exemple: %ld ou %lf), elles NE sont PAS supportées par PA_OutputText() !
Voici un bout de code qui permet d’afficher la position du stylet... (vous allez bientôt voir comment utiliser le stylet...)
PA_OutputText(1,0,0,"Stylus X : %d Stylus Y : %d", Stylus.X, Stylus.Y);
La première chose que vous voyez, c’est le %d... il est utilisé pour afficher des entiers (s32...). Si vous mettez %d quelque part dans le texte, il va chercher l’argument dans ceux que vous lui avez passé (Stylus.X et Stylus.Y, dans ce cas). Si vous avez plusieurs fois %d, il va alors prendre les arguments par ordre d’apparition... ainsi, le premier ‘%d’ est pour Stylus.X, le second pour Stylus.Y, etc...
L’affichage de floats n’est pas très différent de celui des entiers, il n’y a que 2 choses qui diffèrent:
Vous allez alors obtenir quelque chose comme ceci :
float test = 4.678; PA_OutputText(1,0,0,"Float value : %f", test);
Vous voyez, ce n’est pas très difficile ! Cela va afficher Float value : 4.678
La dernière chose à savoir est comment afficher des chaînes de caractères... C’est très pratique, cela vous permet par exemple, d’intégrer le nom du joueur dans vos textes, et ainsi avoir un message personnalisé! Utilisez juste %s, pour les chaînes de caractères !
Cela va alors vous donner :
char name[10] = "Mollusk"; PA_OutputText(1,0,0,"Hi %s", name);
Vous voyez, rien d’insurmontable... cela va vous afficher Hi Mollusk. Une chose importante : votre chaîne de caractères, qui est en fait un tableau (array) de caractères (chars), DOIT avoir comme caractère final un \0... si vous n’en mettez pas, l’affichage du texte va continuer jusqu’à ce qu’il tombe sur un \0, ce qui peut prendre un bon bout de temps... De ce fait, si vous ajoutez des lettres une par une dans une chaîne de caractères, comme ‘a’, puis ‘b’, etc... n’oubliez pas de toujours insérer un \0 à la fin de cette dernière.
Il y a 3 façons différentes pour choisir une couleur à un texte :
Vous pouvez, à n’importe quel moment, changer la couleur de la police de caractère en utilisant une simple fonction : PA_SetTextCol(écran, r, g, b). Cela permet d’initialiser la couleur des textes sur un écran... TOUT le texte présent sur cet écran sera alors de la même couleur, même si vous l’avez écrit avant de changer la couleur.
mais que sont les valeurs r, g, et b ??
Voici quelques exemples :
Vous pouvez vérifier l’exemple Text/Text, il utilise cette méthode
PA_SetTextTileCol est légèrement différente de PA_SetTextCol, car elle ne change pas la couleur du texte déjà existant... Mais elle autorise le fait d’avoir différentes couleurs sur le même écran (ce qui est très sympa
). L’exemple de PAlib auquel vous pouvez vous référer est Text/TextColors
PA_SetTextTileCol(1, i); // Change la couleur de l'écran du haut, valeur de 0 à 6 PA_OutputSimpleText(1, 2, i, "Color test..."); // L'écran 1 a une couleur différente
PA_SetTextTileCol(1, n); Initialise la couleur des nouveaux textes à i... ni plus, ni moins. n peut prendre des valeurs allant de 0 à 7, essayez pour voir quelles couleurs cela vous donne...
de 0 à 9: blanc, rouge, vert, bleu foncé, violet, bleu clair, jaune, gris, gris foncé, noir (invisible si le fond d’écran est noir).
La dernière possibilité pour changer la couleur d’un texte est d’utiliser l’entrée %cX dans vos chaînes de caractères, X étant le numéro de la couleur (0-9, comme écrit précédement). Le coté sympa de cette méthode est que vous pouvez vous permettre de mettre de multiples couleurs dans la même chaîne de caractère ! L’exemple vient de TextColors, encore une fois :
PA_OutputText(0, 0, 0, "Test couleur...%c1une autre, %c2encore, %c3 encore...");
Comme vous pouvez le constater, %cX change la couleur (testez le sur émulateur si vous ne me croyez pas
. C’est simple, facile, et... simple, lol.
PA_lib vous permet de personaliser la police de votre texte et la bordure de votre texte facilement.
Il y a typiquement 3 types d’entrées sur la DS : en utilisant le pad (toutes les touches...), le stylet, ou le clavier PAlib... Une dernière méthode utilise le microphone, mais nous reparlerons de cela plus tard, dans le tutorial sur le son...
L’utilisation du pad peut difficilement être plus facile ! Elle est automatiquement mise à jour toutes les frames, et une simple structure vous en donne l’accès. La structure est appelée ‘Pad’, et elle contient les structures multiples, selon le type de pression : Held (appuyé, tenu), Released (relaché), and Newpress (nouvelle pression).
Chaque structure de pression contient alors une liste de toutes les touches :
Donc, pour finir, pour vérifier l’état d’une touche, vous disposez de Pad.Checktype.Keyyoucheck : Verifier que A est appuyé revient à coder Pad.Held.A ! Pad.Released.A correspond à verifier le relachement de A, et Pad.Newpress.A pour detecter une nouvelle pression...
Comme vous pouvez le voir, c’est facile. Voici un code simple et rapide qui ne fonctionne pas mais montre juste comment employer les touches :
if(Pad.Held.Up) { MoveUp(); } if(Pad.Held.Down) { MoveDown(); }
Simple, n’est-ce pas ?
Vérifiez les exemples d’entrée de touches si vous voulez...
— Mollusk 29/11/2005 22:44
Le stylet fonctionne plus ou moins pareil que les touches... Il est automatiquement mis à jour toutes les frames, et utilise une structure appelée Stylus (simple...) Les différentes variables du stylet sont :
Voici un exemple basique :
if (Stylus.Held) { PA_SetSpriteXY(screen, sprite, Stylus.X, Stylus.Y); }
Comme vous pouvez le constater, ce code simple vérifie que le stylet est pressé. Si le stylet est appuyé sur l’écran, il placera le coin supérieur gauche du sprite à la position du stylet... Rien de plus à dire
Regardez l’exemple d’entrée du stylet si vous voulez...
L’utilisation de clavier PAlib est très simple et facile, comme vous pouvez le voir dans l’exemple
Pour fonctionner, le clavier doit être chargé sur un fond donné (chiffre 0 à 3) spécifique.
PA_Init(); // Initialisation de PA_Lib PA_InitVBL(); // Initialisation de la VBL standard PA_InitText(1, 0); // Initialisation du système de texte PA_InitKeyboard(2); // Chargement du clavier sur le fond 2... PA_KeyboardIn(20, 100); // Fait glisser le clavier par le bas jusqu'à-ce qu'il soit en place PA_OutputSimpleText(1, 7, 10, "Text : "); s32 nletter = 0; // Lettre suivante à écrire. 0 puisqu'il n'y a pas encore de lettre char letter = 0; // Nouvelle lettre à écrire char text[200]; // Ce sera notre texte // Boucle infinie while (1) { // On vérifie d'abord les changement de couleurs, avec A,B et X if (Pad.Newpress.A) PA_SetKeyboardColor(0, 1); // Bleu et Rouge if (Pad.Newpress.B) PA_SetKeyboardColor(1, 0); // Rouge et Bleu if (Pad.Newpress.X) PA_SetKeyboardColor(2, 1); // Vert et Rouge if (Pad.Newpress.Y) PA_SetKeyboardColor(0, 2); // Bleu et Vert letter = PA_CheckKeyboard(); if (letter > 31) { // Il y a une nouvelle lettre text[nletter] = letter; nletter++; } else if ((letter == PA_BACKSPACE)&&nletter) { // Touche 'effacement arrière' enfoncée ^^ nletter--; text[nletter] = ' '; // Effacer la dernière lettre } else if (letter == '\n'){ // Touche 'Entrée' enfoncée text[nletter] = letter; nletter++; } PA_OutputText(1, 8, 11, text); // Ecrire le texte PA_WaitForVBL(); }
J’imagine que c’est un exemple assez complexe (comparé aux autres...), alors on va l’analyser étape par étape.
Ca commence par une initialisation du texte, parce qu’...on a besoin d’afficher du texte !
On a ensuite
PA_InitKeyboard(2); // Chargement du clavier sur le fond 2... PA_KeyboardIn(20, 100); // Fait glisser le clavier par le bas jusqu'à ce qu'il soit en place
if (letter > 31) { // Il y a une nouvelle lettre text[nletter] = letter; nletter++; }
J’ai sauté quelques lignes de codes (les lignes de ‘Back space’ et ‘Entrée’) parce que même si ce code est dans l’exemple, vous devriez le comprendre par vous-même
Compilez et testez cette démo, elle fonctionne même sous Dualis !
Ce dernier dispositif est assez intéressant… Vous pouvez l’employer de 2 manières différentes :
Ce code va vous permettre de récupérer des lettres en utilisant le système de reconnaissance d’écriture...Il s’améliorera avec le temps ! Le code est basé en grande partie sur le premier exemple de clavier, donc il n’est pas difficile de le comprendre. Il y a quelques obscurs trucs ‘8 bits’ que nous verrons plus tard avec les fonds d’écran ou backgrounds
Le code se trouve dans Input/RecoGraffiti.
PA_InitText(1, 0); // Initialise le système de texte sur l'écran du haut PA_Init8bitBg(0, 0); // Nous allons dessiner maintenant... u16 *pal = (u16*)PAL_BG0; pal[1] = PA_RGB(31, 31, 31); // couleurs... PA_WaitForVBL(); u8 nletter = 0; char text[200]; // Ce sera notre texte // Boucle inifinie pour laisser tourner le programme while (1) { if(Stylus.Newpress) PA_Clear8bitBg(0); // Reset de l'écran lors de la saisie d'un nouveau caractère PA_8bitDraw(0, 1); char letter = PA_CheckLetter(); // Renvoi la lettre !!! if (letter > 31) { // il y a une nouvelle lettre text[nletter] = letter; nletter++; } else if ((letter == PA_BACKSPACE)&&nletter) { // Backspace pressé nletter--; text[nletter] = ' '; // Efface la lettre précédente } else if (letter == '\n'){ // Enter pressé text[nletter] = letter; nletter++; } PA_OutputText(1, 2, 2, text); // Ecrit le texte PA_OutputSimpleText(1, 0, 10, "Draw a PAGraffiti letter to have it recognized by the system..."); PA_WaitForVBL(); }
Maintenant allons-y pas à pas...
PA_InitText(1, 0); // Initialise le système de texte sur l'écran du haut PA_Init8bitBg(0, 0); // Nous allons dessiner maintenant... u16 *pal = (u16*)PAL_BG0; pal[1] = PA_RGB(31, 31, 31); // couleurs... PA_WaitForVBL();
Cette partie initialise le texte et le fond d’écran ‘dessinable’, vous en apprendrez plus la dessus plus tard...
nletter = 0; sera utilisé pour compter les lettresif(Stylus.Newpress) PA_Clear8bitBg(0); // Reset de l'écran lors de la saisie d'un nouveau caractère PA_8bitDraw(0, 1);
Ceci est du code utilisé pour dessiner sur l’écran et l’effacer si vous pressez le stylet à nouveau...plus tard, plus tard...
char letter = PA_CheckLetter(); // Renvoi la lettre !!!
Maintenant nous y arrivons ! Ce code contrôle la lettre !!! Doit être appelé à chaque ‘cycle’ ou frame pour fonctionner (comme le clavier...). Renvoie 0 si la lettre n’est pas terminée...
Et le reste du code est IDENTIQUE à celui de l’exemple du clavier, n’en parlons plus !
Ce qui est vraiment bien avec ce système, c’est que vous pouvez définir vos propres formes ! En ajouter n’est qu’une question de secondes, et l’exemple est là pour vous guider...
Ce code est situé dans Input/RecoAddShape ,
PA_UsePAGraffiti(0); // Ne pas utiliser les PAgraffitis par défaut PA_RecoAddShape('a', "AAAAAAAAAAAAAAA"); // Ligne droite vers la droite PA_RecoAddShape('b', "111111111111111"); // Ligne droite vers la gauche PA_RecoAddShape('c', "IIIIIIIIIIIIIII"); // Ligne droite vers le haut PA_RecoAddShape('d', "999999999999999"); // Ligne droite vers le bas PA_WaitForVBL(); // Boucle inifinie pour laisser tourner le programme while (1) { if(Stylus.Newpress) PA_Clear8bitBg(0); // Reset de l'écran lorsqu'on commence une nouvelle lettre PA_8bitDraw(0, 1); char letter[2]; letter[1] = 0; letter[0] = PA_CheckLetter(); // renvoi la lettre !!! if (Stylus.Released){ // A n'afficher que lors du levée du stylet PA_OutputText(1, 2, 7, "Shape Recognized : %s", letter); // Lettre reconnue PA_OutputText(1, 0, 1, "A for right, B for left, C for up, D for down"); } PA_OutputText(1, 4, 22, "Shape : %s", PA_RecoShape); // Ecrire la chaîne de caractéres correspondant à la forme tracée PA_OutputSimpleText(1, 0, 10, "Draw a PAGraffiti letter to have it recognized by the system..."); PA_WaitForVBL(); }
Maintenant les commentaires :
PA_UsePAGraffiti(0); Enléve la reconnaissance par défaut. Seules vos formes seront reconnues
PA_RecoAddShape('a', "AAAAAAAAAAAAAAA"); // Ligne droite vers la droite PA_RecoAddShape('b', "111111111111111"); // Ligne droite vers la gauche PA_RecoAddShape('c', "IIIIIIIIIIIIIII"); // Ligne droite vers le haut PA_RecoAddShape('d', "999999999999999"); // Ligne droite vers le bas
C’est là que nous indiquons à PAlib les nouvelles formes à reconnaître grâce à une chaîne de caractéres... Cela ne parait pas très intuitif... Comment l’obtenir ? En lançant cette rom, lol ! Vous verrez un peu plus loin.
Tout ce que vous devez comprendre est qu’une forme est définie par 2 paramétres :
Le reste du code est trés similaire à l’exemple précédent, donc il ne sera pas commenté. Seule une ligne reste importante :
PA_OutputText(1, 4, 22, "Shape : %s", PA_RecoShape); // Ecrire la chaîne de caractéres correspondant à la forme tracée
PA_RecoShape est la chaîne de caractéres correspondant à la forme déssinée... C’est comme cela que j’ai créé les 4 formes reconnues de ce tuto !
Et voilà, le programme reconnaitra les formes que nous avons choisi
J’ai ajouté tardivement un troisiéme exemple pour coller à la dernière version de la lib... Cela ajoute des informations à la reconnaissance de forme. L’information est basique, mais elle peut être vraiment utile dans certains contextes. L’information est stockée lors du Stylus.Released dans une structure appelée PA_RecoInfo. Cela contient :
Ici se trouve le code l’utilisant, qui est juste un ‘copier/coller’ du code des ‘formes personnalisées’, donc je poste juste les choses modifiées...tout ceci dans la boucle infinie...
if (Stylus.Released){ // ne montrer que si le stylet est relevé PA_OutputText(1, 2, 7, "Shape Recognized : %s", letter); // lettre reconnue PA_OutputText(1, 0, 1, "A for right, B for left, C for up, D for down"); // Utilisation de toutes les infos pour tracer le dessin, début et fin... // Rectangle autour de la zone de dessin PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.minY, 2); PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.maxY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2); PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.minX, PA_RecoInfo.maxY, 2); PA_Draw8bitLine(0, PA_RecoInfo.maxX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2); // marquage des points de départ et de fin du dessin : PA_Put8bitPixel(0, PA_RecoInfo.startX, PA_RecoInfo.startY, 2); PA_Put8bitPixel(0, PA_RecoInfo.endX, PA_RecoInfo.endY, 2); } PA_OutputText(1, 4, 22, "Shape : %s", PA_RecoShape); // Ecrire la chaîne de caractéres reconnue en fonction du dessin PA_OutputText(1, 4, 23, "Length : %d pixels ", PA_RecoInfo.Length); // Longueur en pixels
Je ne vais pas ré-expliquer ce que je viens de dire
Je n’aime pas me répéter, lol.
En fait, le code qui pourra être utilisé pour dessiner une boite autour de la forme est :
PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.minY, 2); PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.maxY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2); PA_Draw8bitLine(0, PA_RecoInfo.minX, PA_RecoInfo.minY, PA_RecoInfo.minX, PA_RecoInfo.maxY, 2); PA_Draw8bitLine(0, PA_RecoInfo.maxX, PA_RecoInfo.minY, PA_RecoInfo.maxX, PA_RecoInfo.maxY, 2);
Ceci ne fait que dessiner 4 lignes en utilisant les positions min/max X/Y, facile...
Ensuite, 2 pixels sont dessinés aux positions de départ et d’arrivée :
PA_Put8bitPixel(0, PA_RecoInfo.startX, PA_RecoInfo.startY, 2); PA_Put8bitPixel(0, PA_RecoInfo.endX, PA_RecoInfo.endY, 2);
...
Et la longueur est affichée par PA_OutputText(1, 4, 23, “Length : %d pixels “, PA_RecoInfo.Length);
Rien de plus, rien de moins...Si vous constatez des manques, quelques infos oubliées que vous considerez comme vitales, mailez-moi SVP (Mollusk) ou postez sur le forum...
Oh, et je ne vous ai pas parlé d’ Angle dans cet exemple, car il n’est pas vraiment utile...
Q1. La position du stylet est complètement décalée ! Vous pouvez arranger ça?!?
Note: Pour les personnes ayant 20 pixels de décalage (Par exemple, lorsque vous touchez ‘Q’ vous obtenez ‘A’), allez dans l’écran de calibration de la DS, et touchez juste à côté de la marque indiquée. Cela devrait arranger les choses. Vous devrez cependant recalibrer pour d’autre applications (les jeux par exemple).
Q2. Lorsque j’utilise Dualis et que je simule le stylet par un clic de souris, ça plante!
Q3. Comment tester si le stylet touche une zone (sans utiliser de sprites)?
Cette fonction vérifie si le stylet est dans un rectangle défini par les paramètres de la fonctions. Exemple :
if(PA_StylusInZone(x1,y1,x2,y2))
{
PA_OutputText(1,1,1,”OK”);
}
Vous pouvez allez voir la documentation de PA_StylusInZone() pour - un peu - plus de précision.
Prochain → Jour 4 - Sprites