Documentation du TileMap Engine v0.3 (19/01/2004)



Introduction


Avant de passer à la description des fonctions, je préfère présenter le mode de fonctionnement de la librairie.

En premier lieu, voici les domaines où l'utilisation de la librairie se révèle judicieuse :
Et voici ceux où la librairie ne devrait pas être utilisée : La librairie est donc adaptée aux jeux nécessitant un arrière-plan de grande taille (en tout cas, plus large que l'écran d'une TI92+), et que l'on doit déplacer avec une précision au pixel près.

Pour cela voici le procédé utilisé : le plan (la map, le niveau), est représenté par un tableau à deux dimensions, une case représente un carré de 16x16 pixels (ou 8x8 selon les cas), elle correspond donc à un sprite de cette même taille. Chaque case devra donc contenir le numéro du sprite correspondant, et tous les sprites seront alors rangés dans une liste de sprites (afin de pouvoir y accéder à partir de leur numéro).
Cette méthode présente un premier avantage : on peut utiliser un même sprite plusieurs fois dans le niveau, et on obtient ainsi un gain important de place puisque le sprite n'est défini qu'une seule fois, et partout où il est utilisé, on ne le référence que par son numéro, qui prendra 1 ou 2 octets selon que l'on utilisera une matrice d'octets ou de word, au lieu de 8 ou 32 selon que l'on utilisera des sprites 8x8 ou 16x16.
Ensuite, pour afficher le plan à l'écran, il faut passer par deux étapes : d'abord, on recopie grossièrement la zone du plan que l'on veut afficher dans un écran virtuel plus large que l'écran réel (32 pixels de plus en hauteur et en largeur pour être précis, ce qui fait que cet écran virtuel aura une taille de (240+32)*(128+32)/8 = 5440 octets).
Et enfin, on affiche cet écran virtuel à l'écran, en décalant en même temps l'image pour obtenir a zone exacte que l'on veut afficher.
Cela peut paraître peu subtil d'utiliser un plan intermédiaire, mais c'est en réalité très avantageux car on n'est pas obligé de rafraichir le contenu de l'écran virtuel à chaque image, on le fait seulement lorsque c'est nécessaire, c'est-à-dire lorsque l'on veut animer des tiles (3 à 4 fois par secondes en général, c'est-à-dire une image sur 5-6 pour un jeu à 20 fps) ou lorsque l'on dépasse les limites de l'écran virtuel (il n'a que 32 pixels de plus que l'écran normal, donc il faut rafraichir le buffer 1 fois sur 32 pour un jeu avec un déplacement de 1 pixel par image).
Cela permet à la fonction qui recopie cet écran virtuel plus grand vers l'écran de taille normale d'être très optimisée pour faire précisément cette tâche plutôt que de devoir s'adapter à une taille quelconque. Cette fonction est donc appelée à chaque image et est très rapide.

Voici un schéma pour vous aider à visualiser le principe de fonctionnement :
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|01|01|01|00|00|00|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|01|01|01|01|01|01|00|00|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|01|01|01|01|00|00|01|01|01|01|01|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|01|01|01|01|00|00|00|01|01|01|01|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|01|01|01|01|01|01|00|01|01|01|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|01|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|01|01|01|01|01|01|01|01|01|01|01|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|00|01|01|01|01|01|01|01|01|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|00|00|00|01|01|01|01|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|00|00|00|00|00|00|00|00|00|00|00|00|01|00|00|00|00|00|00|00|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Voici notre plan, en rouge est représentée la zone que l'on désire afficher. Dans cet exemple, seuls deux sprites différents sont utilisés, le sprite n°1 est mis en gras pour une meilleure visibilité. Ce plan pourrait être utilisé dans un RPG, pour représenter par exemple une île entourée d'eau, avec un lac au centre (le sprite 0 serait de l'eau et le sprite 1 serait de la terre).
Chaque case représente un sprite de 16x16 pixels.
On peut déjà noter que la zone rouge fait 272x160 pixels, c'est-à-dire (240+32)x(128+32), donc en réalité, on n'affichera pas la totalité de la zone rouge à l'écran, mais seulement une partie.

La zone rouge est entièrement copiée dans le grand écran virtuel (en remplaçant, bien sûr, les numéros par leur sprite correspondant).
Voici donc ce qu'on obtient sur le grand écran virtuel :
              272
     <----------------->
   ^ +-----------------+
   | |    ######       |
   | |   ##########    |
   | |   ####  #####   |
   | |  ####   ####    |
160| |  ###### ###     |
   | |   ###########   |
   | |      ########## |
   | |      ###########|
   | |       ########  |
   | |         ####    |
   v +-----------------+
Les sprites n°1 seront représentés par '#', et les sprites n°0 par ' '.
Il ne reste plus maintenant qu'à afficher la partie de cet écran virtuel que l'on souhaite voir, dans le vrai écran (de 240x128 pixels).
La précision de mes shémas ne me permet plus de dessiner cette dernière phase, je vais donc ne dessiner qu'une partie de l'écran de taille normale.
Supposons que l'on veuille par exemple, afficher la zone commençant aux coordonnées 35 en abscisse et 21 en ordonnée.
On a pour cela dans le grand écran virtuel la zone de la map commençant aux coordonnées (32 ; 0). Il faut donc afficher le contenu du grand écran virtuel à partir de son 4ème pixel en abscisse et de son 22ème en ordonnée.
Le résultat sur l'écran de taille normale ressemblera à ça :
            16
    <---------------->
  ^ +----------------+----------------+----------------+---------------
  | |             |  |           ^ |  |             |  |             | 
  | |             |  |           | |  |             |  |             | 
  | |             |  |         11| |  |             |  |             | 
16| |      13     |  |           | |  |             |  |             | 
  | |<----------->|  |           v |  |             |  |             | 
  | |-------------+--|-------------+--|-------------+--|-------------+-
  | |             |  |             |  |             |  |             | 
  | |             |  |             |  |             |  |             | 
  v +----------------+----------------+----------------+---------------
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |-------------+--|-------------+--|-------------+--|-------------+-
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    +----------------+----------------+----------------+---------------
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |             |  |             |  |             |  |             | 
    |-------------+--|-------------+--|-------------+--|-------------+-
    |             |  |             |  |             |  |             | 
Je n'ai représenté qu'une partie de l'écran (en noir). En gris clair, j'ai représenté le grand écran virtuel : en fait, ce sont les limites entre les cases 16x16.


Comment utiliser la librairie dans vos programme ?

Avec TIGCC IDE, ajoutez les fichiers TileMap.a et Tilemap.h à votre projet, et tapez #include "TileMap.h" dans votre fichier source.


Les fonctions de la librairie

Les fonctions fournies par la librairie peuvent se classer en deux catégories : les fonctions de bas niveau (puissantes, mais compliquées à utiliser) et les fonctions de haut niveau (beaucoup plus simple à utiliser, mais très légèrement moins efficaces).
Dans le cas général, les fonctions de haut niveau devraient suffir, mais si vous voulez faire un jeu complexe, et qui nécessite de la puissance ou si vous programmez en assembleur, alors vous devriez utiliser les fonctions de bas niveau.
Il est possible de faire avec les fonctions de haut niveau tout ce que l'on peut faire avec celles de bas niveau à l'exception de l'utilisation des tables de décalages de lignes.

Si vous programmez en assembleur, sachez que les paramètres des fonctions sont passés directement par les registres, reportez vous au header pour connaître les registres coresspondant aux paramètres d'une fonction.



  1. Spécifications des structures de données
  2. Depuis le début, nous parlons de matrice de tiles, de liste de sprites, de grand écran virtuel, ou d'écran virtuel simple, sans vraiment avoir précisé quelles étaient leurs spécificités.

    Matrice de tiles
    Tableau de char ou de short, à deux dimensions, ayant au minimum 8 lignes et 15 colonnes si on utilise des sprites 16x16, ou 16 lignes et 30 colonnes avec des sprites 8x8.


    Sprites
    Les sprites peuvent être en noir et blanc ou en niveaux de gris, et de taille 8x8 pixels ou 16x16. Il y a des fonctions spécifiques pour chaque type de sprite, il ne faut donc pas se tromper en les choisissant.
    Les sprites en noir et blanc sont classiques : un tableau de 8 char pour les sprites 8x8, ou un tableau de 16 short pour les sprites 16x16, contenant successivement chaque ligne du sprite.
    Les sprites en niveaux de gris utilisent un format un peu plus compliqué : c'est un tableau de 16 char pour les sprites 8x8 ou 32 short pour les sprites 16x16 qui est organisé comme ceci : ligne1/plan1, puis ligne1/plan2, puis ligne2/plan1, puis ligne2/plan2, etc... On appelle cela un format entrelacé. Le plan1 peut-être celui correspondant au gris clair au au gris foncé, cela n'a pas d'importance tant que vous respectez la même convention pour les écrans virtuels (voir plus bas).


    Liste de sprites
    La liste peut être vue comme un tableau à une dimension contenant des sprites, mais en réalité, c'est un tableau à deux dimensions, puisque les sprites eux aussi sont des tableaux à une dimension.


    Tableau d'animation
    Tableau de short à deux dimensions : le nombre d'étape d'animation et le nombre d'animations. Chaque ligne représente une étape, et chaque colonne représente une animation, ainsi l'élément du tableau situé sur la colonne c et la ligne l sera le numéro du sprite de la lième étape de la cième animation.
    Le tableau ne peut être qu'un tableau de short, car j'ai pensé que si vous utilisez des tiles animés vous aurez probablement beaucoup de sprites.


    Table de décalage horizontal
    Tableau de char à une dimension, de 128 éléments. Chaque élément représente le décalage individuel horizontal à ajouter à celui de la ligne courante lors de la recopie du grand écran virtuel vers l'écran. Les valeurs autorisées sont comprises entre 0 et 16.


    Table de décalage vertical
    Tableau de short à une dimension, de 128 éléments. Chaque élément représente la valeur à ajouter à l'adresse source à la fin de chaque ligne lors de la recopie du grand écran virtuel vers l'écran. Toutes les valeurs sont permises, mais faites attention à ne pas sortir du grand écran virtuel.


    Grand écran virtuel
    Zone mémoire de 5440 octets si vous travaillez en noir et blanc, ou bien deux fois plus grande (10880 octets) si vous travaillez en niveaux de gris (dans ce cas, les 5440 premiers octets correspondront au Plan1, et les 5440 suivant correspondront au Plan2, vous choisissez comme il vous arrange de définir le Plan1 gris clair ou gris foncé, mais respectez cette convention dans vos sprites).


    Ecran virtuel
    Zone mémoire de 3840 octets en noir et blanc, ou le double (7680 octets) si vous travaillez en niveaux de gris (dans ce cas, comme pour le grand écran virtuel, les deux plans seront adjacents, à vous de choisir lequel sera le plan foncé et lequel sera le plan clair).


  3. Les fonctions de haut niveau

  4. Notez que les prototypes et l'utilisation des fonctions de ce tilemap engine peuvent/vont changer dans ExtGraph 2.00 Beta 3.



  5. Les fonctions de bas niveau

  6. Notez que les prototypes et l'utilisation des fonctions de ce tilemap engine peuvent/vont changer dans ExtGraph 2.00 Beta 3.

    Il y a plusieurs familles de fonctions qui effectuent les deux tâches primaires de plusieurs façons différentes, pour donner au total pas moins de 64 fonctions différentes, et plus de 380 combinaisons d'utilisation...



La description des fonctions est terminée, je vous recommande de lire les exemples fournis pour bien comprendre l'utilisation des fonctions.
L'exemple 1 (demo13 dans ExtGraph) utilise les fonctions de haut niveau, il montre comment afficher plusieurs plans pour donner une illusion de profondeur (pour un jeu de plate-forme, par exemple).
L'exemple 2 (demo14 dans ExtGraph) est obsolète, il utilise les fonctions de bas niveau, il montre comment faire une map avec des tiles animés (pour un RPG par exemple), mais sans utiliser les fonctions prévues pour les map animées (elles n'étaient pas encore écrites au moment où j'ai fait cet exemple).
L'exemple 3 (demo15 dans ExtGraph) est le même que l'exemple 2, mais en utilisant les fonctions prévues pour.
L'exemple 4 (demo16 dans ExtGraph) utilise les fonctions de bas niveau et les tables de décalage.


Remerciements

  • Je me dois de remercier PpHd car j'ai complètement copié le principe de fonctionnement sur lui
  • Je remercie également Lionel Debroux et Malcolm Smith pour leur aide pour la traduction de la documentation



  • Annexe


    Description des différents modes d'affichage :

    RPLC
    RemPLaCe complètement la destination (il est donc inutile de l'effacer auparavant). Vous devriez utiliser ce mode pour afficher un arrière-plan.


    OR
    OU logique entre la source et la destination.


    XOR
    OU eXclusif logique entre la source et la destination.


    AND
    ET logique entre la source et la destination.


    BLIT
    Ce mode utilise le champ mask du Plane (ou bien le mask peut être passé directement en paramètre avec les fonctions de bas niveau). Un ET logique est effectué entre le mask et la destination, puis le plan est affiché en mode OR. Ce mode peut être utile pour faire des effets de transitions.


    TRANW
    La couleur blanche est TRANsparente, les autres couleurs sont opaques. Ce mode est très utile pour afficher des plans par-dessus un arrière-plan.


    TRANB
    La couleur noire est TRANsparente, les autres couleurs sont opaques. Ce mode est également très utile pour afficher des plans par-dessus un arrière-plan.



    Tableau récapitulatif des différents types de plan :

    ("valeurs" de type TM_Type)
    Matrice de charMatrice de short
    Sprites 8x8Sprites 16x16Sprites 8x8Sprites 16x16
    Noir et blancTM_8BTM_16BTM_8WTM_16W
    Niveaux de grisTM_G8BTM_G16BTM_G8WTM_G16W



    Tableau récapitulatif des différents types de plan animés :

    ("valeurs" de type TM_AnimType)
    Matrice de charMatrice de short
    Sprites 8x8Sprites 16x16Sprites 8x8Sprites 16x16
    Noir et blancTM_A8BTM_A16BTM_A8WTM_A16W
    Niveaux de grisTM_GA8BTM_GA16BTM_GA8WTM_GA16W



    Tableau récapitulatif des différents modes d'affichage :

    ("valeurs" de type TM_Mode)
    RPLCORXORANDBLITTRANWTRANB
    Noir et blancTI92+TM_RPLCTM_ORTM_XORTM_ANDTM_BLIT
    TI89TM_RPLC89TM_OR89TM_XOR89TM_AND89TM_BLIT89
    Niveaux de grisTI92+TM_GRPLCTM_GORTM_GXORTM_GANDTM_GBLITTM_GTRANWTM_GTRANB
    TI89TM_GRPLC89TM_GOR89TM_GXOR89TM_GAND89TM_GBLIT89TM_GTRANW89TM_GTRANB89



    Historique

    v 0.3 (19/04/2004)
    Traduction de la documentation en anglais


    v0.2 (26/12/2003)
    Fonctions d'animation automatique de tiles et de décalages individuels horizontaux et verticaux.
    Correction de quelques bugs sur les fonction BLIT.


    v0.1b (21/12/2003)
    Aucune nouvelle fonction n'a été ajoutée, mais elles ont toutes été réécrites car la taille du grand écran virtuel a été changée, pour lui permettre une meilleure évolution.
    L'utilisation des fonctions de haut niveau ne devrait pas avoir changé, mais celle des fonctions de bas niveau a changé.


    v0.1 (19/12/2003)
    Première version publique


    A faire

    Dans une éventuelle future version, voici ce que je rajouterais (par ordre de priorité) :
  • Plus de modes d'affichage (si par exemple j'ai plusieurs demandes pour un certain mode, je le rajouterai)
  • Editeur de maps/sprites sur PC
  • Flipping horizontal et vertical



  • Contact

    Pour toute remarque, suggestion, report de bug, question, etc...
    Julien Richard-Foy
    julien.rf@wanadoo.fr