Home   Archives    Hardware   Programmation   Challenges   Forum   Le Mag    Faq   La Communauté   L'Equipe
 
L'équipe progG de Ti-Fr

Voici les nicks de vos serviteurs ;-)

chickensaver_john
Kevin Kofler
Thibaut
janjan2
TiMad
Iceman89
fréka
Zewoo
Squale92
Verstand
ZdRUbAl
UtOpIaH

et nEUrOne ...

Une idée ?
Une idée pour améliorez cette partie? ou tout simplement vous souhaitez participer à l'élaborations des tutos.
Mailez-nous ici

Les raccourcis
 

Chapitre XII


    Ce chapitre va nous permettre d'étudier les manipulations de base des sprites, qui sont bien utiles lors de la conception de nombreux jeux...

    Il est possible, sous TIGCC, de créer des sprites en 4 niveaux de gris, mais, dans ce chapitre, nous ne nous intéresserons qu'aux sprites en noir en blanc : nous ne nous soucierons des Sprites en niveaux de gris que plus tard, quand nous auront étudié le mode de fonctionnement de ceux-ci...

    TIGCC permet d'utiliser les sprites, par la librairies <sprites.h>. Celle-ci contient trois fonctions, qui permettent d'utiliser des sprites faisant 8, 16 ou 32 pixels de côté. (En fait, ces sprites doivent faire 8, 16, ou 32, ou moins, de côté, mais, en général, ce sont ces mesures qui sont utilisées, que ce soit par la majorité des jeux, ou par la plupart des logiciels permettant de créer ces sprites.).

 

I:\ Les fonctions de manipulation de sprites :

        A: Les fonctions :

    Nous allons ici étudier les trois fonctions qui permettent d'afficher des sprites sur l'écran de nos TI.

    La première est celle qui permet de dessiner des sprites faisant 8 pixels de côté (ou moins). Sa syntaxe est la suivante :
        Sprite8(x, y, hauteur, sprite, plan, mode);
    Les valeurs x et y sont des nombres de type short, qui servent à définir la position où le sprite sera affiché, en x et en y. La valeur hauteur est aussi de type short, et elle correspond, comme son nom l'indique, à la hauteur du sprite. La valeur sprite est la définition du sprite. Elle correspond à une liste de nombres hexadécimaux. (Nous verrons dans la deuxième partie comment bâtir cette liste). La valeur plan correspond à un pointeur vers la mémoire vidéo (Il est possible, pour faire simple de le faire pointer vers LCD_MEM. Si vous n'utilisez pas d'écran virtuels, et que vous êtes, comme dans ce chapitre, en noir et blanc uniquement, c'est ce qu'il convient de faire.). Enfin, la valeur mode correspond à la façon dont le sprite sera affiché. On peut afficher un sprite de trois façons différentes :

Valeur de mode Résultat obtenu
SPRT_XOR Le sprite est dessiné en XOR sur le fond de l'écran. (Ce mode est utilisé pour les sprites en mode non-masqué).
SPRT_OR Le sprite est dessiné en OR sur le fond de l'écran. (Ce mode est utilisé en association avec SPRT_AND pour les sprites en mode masqué).
SPRT_AND Le sprite est dessiné en AND sur le fond de l'écran. (Ce mode est utilisé en association avec SPRT_OR pour les sprites en mode masqué).

 

    Les deux autres fonctions qui permettent d'utiliser des sprites sont celles qui nous autorisent à dessiner ceux qui font 16 ou 32 pixels de côté (ou moins). Elles sont définies exactement comme la précédente (C'est pour cette raison que nous ne détaillerons pas leur mode de fonctionnement, qui l'a déjà été, pour les sprites de 8 pixels de côté !). 
    La fonction permettant de dessiner des sprites de 16 pixels de côté (ou moins) a la syntaxe suivante :
        Sprite16(x, y, hauteur, sprite, plan, mode);
    Et celle qui permet de dessiner des sprites de 32 pixels de côté (ou moins) a la syntaxe suivante :
        Sprite32(x, y, hauteur, sprite, plan, mode);

        B: Techniques de dessin des sprites :

* Le mode non-masqué :

    Cette technique est la plus ancienne, et peut-être la plus facile à comprendre pour les débutants. (C'est celle qui est utilisée dans le premier exemple que nous étudierons.). Avec cette technique, le sprite est dessiné en mode XOR à sa position, et, pour l'effacer, il suffit de le redessiner un seconde fois, à la même position.

* Le mode masqué :

    Cette technique demande de plus grande connaissances en programmation, mais elle permet généralement d'obtenir de meilleurs résultats. Si vous souhaitez utiliser cette méthode, il vous faudra :

  • Effacer la partie de l'écran qui correspond à l'emplacement où vous souhaitez afficher votre sprite.
  • Dessiner la forme du sprite. Pour cela, il faut dessiner l'inverse du dessin du sprite en mode AND, puis dessiner le sprite en mode OR à la même position.
  • Cependant, il n'est pas simple de retrouver l'écran original. Une techniques parfois utilisée est le "double-buffering", qui consiste à utiliser un écran "réel", et un écran "virtuel". (C'est un peu comme cela que fonctionnent les niveaux de gris sur nos TIs !)

    Le second exemple traite de ce mode.

 

II:\ La définition du sprite :

    La définition du sprite donnée dans la fonction permettant de l'afficher doit être faite sous forme d'une liste composée de nombre hexadécimaux. Ceux-ci correspondent au code (en bits => binaire) de chaque ligne, converti en hexadécimal. Nous allons partir sur l'exemple qui sera repris dans la troisième partie, A. Ici, le sprite sera de 16 pixels sur 16 pixels.
    Il existe deux façons d'obtenir la liste de nombres hexadécimaux. Soit "à la main", soit à partir d'un logiciel conçu pour cela. (De nombreux logiciels de ce type sont disponibles sur Internet.).

        A: Définition "manuelle" d'un sprite :

    Pour commencer, je vous conseille de prendre une feuille de papier quadrillé, et d'y tracer un cadre de 16 carreaux de côté, un peu comme ceci :

Papier quadrillé, en 16*16

    Ensuite, je vous conseille de dessiner votre sprite, en noir et blanc, comme il sera sur l'écran de la TI. pour cela, il vous suffit de noircir les cases qui représenteront des pixels noirs, tout en laissant blancs ceux qui le resteront. Dans le cas de notre premier exemple de programme, on obtiendra ceci :

Le sprite, version papier...

    Après cela, il faut, sur une feuille, par exemple, écrire les codes binaires correspondants à chaque ligne. On obtiendra ceci, si l'on considère toujours le même exemple :

1111111111111111
1100000000000011
1010000000000101
1001000000001001
1000100000010001
1000010000100001
1000001001000001
1000000110000001
1000000110000001
1000001001000001
1000010000100001
1000100000010001
1001000000001001
1010000000000101
1100000000000011
1111111111111111

    Et, enfin, il faut convertir chaque ligne (composée d'un nombre binaire) en un nombre hexadécimal. En conservant le même exemple, on obtient ceci :

1111111111111111    =>    FFFF
1100000000000011    =>    C003
1010000000000101    =>    A005
1001000000001001    =>    9009
1000100000010001    =>    8811
1000010000100001    =>    8421
1000001001000001    =>    8241
1000000110000001    =>    8181
1000000110000001    =>    8181
1000001001000001    =>    8241
1000010000100001    =>    8421
1000100000010001    =>    8811
1001000000001001    =>    9009
1010000000000101    =>    A005
1100000000000011    =>    C003
1111111111111111    =>   
FFFF

    Pour la manipulation que nous venons d'effectuer, vous pouvez sans aucun problème utiliser votre TI. Pour cela, mettez vous en mode Binaire (via la boite de dialogue mode !), puis, dans l'écran HOME tapez ceci : (Pour la première ligne de ce sprite) :
        0b1111111111111111Hex        Puis appuyez sur [ENTER]
    La TI vous renverra comme réponse 0hFFFF

    Il ne reste plus qu'à regrouper les valeurs hexadécimales obtenus en une liste, de type static unsigned short, que nous nommerons dans le premier exemple de programme sprite. Dans la liste, chaque valeur hexadécimale doit être précédée du préfixe "0x". Pour cela, il faut effectuer l'opération suivante :
        static unsigned short sprite[] ={ 0xFFFF, 0xC003, 0xA005, 0x9009, 0x8811, 0x8421, 0x8241, 0x8181, 0x8181, 0x8241, 0x8421, 0x8811, 0x9009, 0xA005, 0xC003, 0xFFFF};

Attention :

  • Pour obtenir des sprites de 8x8 pixels de côté, il faut utiliser un codage sur 8 bits, c'est-à-dire sur un octet. Le type de variable qu'il faudra donc utiliser pour ce type de sprites est : static unsigned char. (Les chars sont codés sur 8 bits).
  • Pour obtenir des sprites de 16x16 pixels de côté, il faudra utiliser un codage sur 16 bits, c'est-à-dire sur deux octets. Le type de variable qu'il faudra donc utiliser pour cette taille de sprites est : static unsigned short. (Les shorts sont codés sur 16 bits).
  • Enfin, pour obtenir des sprites de 32x32 pixels de côté, il faudra utiliser un codage sur 32 bits, c'est-à-dire sur quatre octets. Le type de variable qu'il faudra donc utiliser pour cette taille de sprites est : static unsigned long. (Les longs sont codés sur 16 bits).

 

        B: Définition "logicielle" du sprite :

    Il existe sur Internet de nombreux logiciels qui permettent de dessiner un sprite, et qui renvoient automatiquement la chaîne hexadécimale correspondante, qu'il suffit d'insérer dans le code source du programme. C'est la technique la plus rapide et la plus simple !!! (C'est celle que j'utilise toujours !).
    Par exemple, vous pouvez en télécharger un à cette adresse : www.ticalc.org/archives/files/fileinfo/142/14291.html


        C: Sprite en Binaire, ou en Hexadécimal ??? :

    Depuis la version 0.91 de TIGCC, il est possible d'utiliser des valeurs en Binaire, sans avoir à les convertir en code Hexadécimal, ce qui vous permet de créer vos sprites plus rapidement, et ils peuvent apparaître plus clairement dans le code : il est naturellement plus simple de s'imaginer le dessin représenté par un sprite écrit en binaire qu'en hexadécimal : il suffit dans le premier cas de "remplacer" mentalement les '1' par des points noirs !
    Cependant, je vous conseille, si vous avez l'intention de distribuer le source de votre programme, de prendre le temps de convertir les valeurs Binaires en Hexadécimal, car de nombreuses personnes utilisent encore des version de TIGCC antérieures à la 0.91. Si vous ne le faites pas, ils seront forcés de le faire eux-même, afin de pouvoir compiler le programme, ce qui est, avouez-le long ! Cela dit, si vous ne souhaitez pas passer de temps à cette conversion, prévenez tout de même celui qui lira votre source, par exemple en insérant un commentaire dans celui-ci, prévenant d'éventuels problèmes de compatibilité.

 

II:\ Exemples :

        A: Premier exemple :

    Cet exemple est en fait une "reprise" de celui que nous avons utilisé au Chapitre IV, mais adapté pour les sprites. Nous ne prendrons donc pas la peine de commenter en détails toutes les fonctions, puisque celles-ci l'ont déjà été.
    Ce programme a été écrit pour une TI-92plus. Pour le porter sur TI-89, il faut modifier les valeurs qui correspondent à la taille de l'écran, ainsi que celles qui correspondent aux touches de déplacement du clavier. Ces modifications ont été faites en rouge foncé, en parallèle au code source du programme.

#define OPTIMIZE_ROM_CALLS
#define SAVE_SCREEN
#include <tigcclib.h>

short
_ti92plus;

void _main(void)
{
 
static unsigned short sprite[] = {0xFFFF, 0xC003, 0xA005, 0x9009, 0x8811, 0x8421, 0x8241, 0x8181, 0x8181, 0x8241, 0x8421, 0x8811, 0x9009, 0xA005, 0xC003, 0xFFFF};
// Cette ligne de code correspond à la définition du sprite.

 
short key = 0;
// Crée la variable de touche pressée au clavier.
 
short xxa = 0;
// Crée la variable de position selon x.
 
short yya = 0;
// Crée la variable de positon selon y.

 
xxa=0, yya = 0;
// Place la valeur 0 dans les variables de position.
 
ClrScr();
// Efface l'écran.

 
do
 
{

   
if(key != 0)
   
Sprite16(xxa, yya, 16, sprite, LCD_MEM, SPRT_XOR);
/* Pour que le sprite ne soit pas effacé la première fois.
(quand aucune touche n'a été pressée.)*/

   
switch(key)
    {
// Boucle qui examine la valeur de "key".

     
case 340: // Si key vaut 340 (touche droite a été pressée).    344 sur TI-89
     
if(xxa+16 < 240) // Pour que le texte ne sorte pas de l'écran.    160 sur TI-89
        xxa = xxa+2; // Déplace le texte de 5 pixels vers la droite.
     
break; // Fin de ce cas.

     
case 337: // Si key vaut 337 (touche gauche a été pressée).    338 sur TI-89
     
if(xxa > 0) // Pour que le texte ne sorte pas de l'écran.
       
xxa = xxa-2; // Déplace le texte de 5 pixels vers la gauche.
     
break; // Fin de ce cas.

     
case 344: // Si key vaut 344 (touche bas a été pressée).    340 sur TI-89
     
if(yya+16 < 128) // Pour que le texte ne sorte pas de l'écran.    100 sur TI-89
        yya= yya+2; // Déplace le texte de 5 pixels vers le bas.
     
break; // Fin de ce cas.

     
case 338: // Si key vaut 338 (touche haut a été pressée).    337 sur TI-89
     
if(yya > 0) // Pour que le texte ne sorte pas de l'écran.
       
yya = yya-2; // Déplace le texte de 5 pixels vers le haut.
     
break; // Fin de ce cas.

   
} // Fin de cette boucle "switch()";

   
Sprite16(xxa, yya, 16, sprite, LCD_MEM, SPRT_XOR);
// Pour dessiner le sprite à la nouvelle position.

   
key = ngetchx();
// Attend qu'une touche soit pressée, et stocke sa valeur dans key.

 
} // Fin de la boucle "do{}".

 
while(key != 264);       // Même valeur sur TI-89
// Tout ce qui a été décrit précédemment est valable jusqu'à ce qu'on appuie sur ESC.

 
ClrScr(); // Efface l'écran
 
DlgMessage("Au revoir !","En espérant être utile... www.ti-fr.org",BT_NONE,BT_NONE);
// Affiche une boite de dialogue donnant l' adresse du site où vous avez trouvé ce tutorial.

}

 

        B: Second exemple :

    Cet exemple est destiné à vous monter une utilisation possible des sprites en utilisant la technique des sprites masqués.

#define OPTIMIZE_ROM_CALLS
#define SAVE_SCREEN
#include <tigcclib.h>

short _ti92plus;

void _main(void)
{

  static unsigned short sprite[] = {0xFFFF, 0xC003, 0xBFFD, 0xB00D, 0xA815, 0xA425, 0xA3C5, 0xA3C5, 0xA3C5, 0xA3C5, 0xA425, 0xA815, 0xB00D, 0xBFFD, 0xC003, 0xFFFF};
// Déclaration du sprite

  static unsigned short inverse[] = {~0xFFFF, ~0xC003, ~0xBFFD, ~0xB00D, ~0xA815, ~0xA425, ~0xA3C5, ~0xA3C5, ~0xA3C5, ~0xA3C5, ~0xA425, ~0xA815, ~0xB00D, ~0xBFFD, ~0xC003, ~0xFFFF};
// Déclaration de l'inverse du sprite.

 
short i;
// Déclaration de la variable i, qui sera utilisée dans la boucle for suivante.

  ClrScr();
// Efface l'écran

 
for(i=0 ; i<241 ; i++)
  {
    DrawLine(i, 0, i, 128, A_SHADE_PS);
    DrawLine(i, 0, i, 128, A_SHADE_NS);
  }
// Cette boucle for permet de dessiner des petits carrés noirs sur fond blanc sur tout l'écran, ce qui nous permettra par la suite de voir le résultat de l'affichage du sprite...

 
Sprite16(50, 50, 16, inverse, LCD_MEM, SPRT_AND);
  ngetchx();
// Dessine l'inverse du sprite en mode AND, et attend qu'on presse une touche

 
Sprite16(50, 50, 16, sprite, LCD_MEM, SPRT_OR);
  ngetchx();
// Dessine le sprite en mode OR, et attend qu'on presse une touche

}

 

    Et voilà, vous avez atteint la fin de ce Chapitre, qui, je l'espère, vous a permis d'apprendre, et surtout de comprendre, les manipulations faisables avec des sprites en noir et blanc. Peut-être que je rédigerai, un jour, un chapitre concernant les sprites en niveaux de gris...

Retour au menu général

Chapitre XIII


 


Copyright © Ti-Fr v2.0 1999-2002