Table des matières

DrawLib

lib et documentation rédigée par Julien P. (Orwell).

telechargement :

http://orwell01.free.fr/Release/Drawlib/

Pourquoi Drawlib

Le fait d’afficher des sprites est devenu quelque chose d’extrêmement courant dans les programmes que l’on écrit actuellement pour notre petite caltoche, qu’il s’agisse de jeux ou d’autre chose. Tout le monde souhaite pouvoir les utiliser le plus rapidement possible, alors qu’en fait l’affichage d’une image à l’écran n’a rien d’une opération facile! Si on travaille en gris, il faut gérer les 3 couleurs, la transparence, le clipping, tout ca sur un écran dont la configuration n’est pas des plus simples.

En plus, puisqu’un pixel est représenté par un (ou 2) bit en mémoire et qu’on manipule toujours des octets et des mots (c’est-à-dire des groupes de 8 ou 16 bits), on doit toujours essayer de travailler avec des sprites de 8 ou 16 pixels de large parce que c’est plus simple à manipuler etc...

L’idée ici est de fournir (non plus une seule mais) plusieurs fonctions générales capables de tout faire à la fois, quelles que soient les dimensions du sprite que l’on souhaite afficher. Ces fonctions servent uniquement pour le mode DB, peuvent gérer la transparence en utilisant des masques, et peuvent également gérer le clipping (donc veiller à ce que ce qui sort d’un côté de l’écran n’apparaisse pas de l’autre côté). Elles travaillent avec des données compressées, c’est-à-dire que les 3 couches (masque/avant-plan/arrière-plan) ont été rassemblées en 2.

Une ligne de 8 pixels sera donc codée en 2 octets, et plus en 3.

Ces fonctions ont donc quelques avantages:

- UNE image = UN sprite = UN tableau = UN appel de fonction pour l’afficher; - Gain de place important pour l’enregistrement des sprites;

- Emploi de pointeurs far: les sprites peuvent être enregistrés n’importe où en mémoire et affichés directement (on peut afficher des sprites placés en memzone par exemple)

- Codage rapide des sprites avec Sprite Maker.

Plutôt que d’avoir une seule fonction qui gère à la fois les masques et le clipping, on peut maintenant choisir si oui ou non on veut utiliser des masques et si oui ou non on doit veiller à éviter le clipping.

Nouveautés par rapport à la version 1.4

- Révision complète du clipping: fonctions mask+clip et nomask+clip nettement moins volumineuses; - Le cadre de clipping peut maintenant être configuré comme on veut.

On peut ainsi empecher les 2 fonctions citées ci-dessus d’afficher quoi que ce soit en dehors d’un cadre défini dans l’écran, quelles que soient ses dimensions et sa position (tout en restant à l’intérieur de l’écran bien entendu).

Les 2 autres fonctions seront toujours capables d’afficher en dehors de ce cadre.

- Bug corrigé: Les compilateurs râlent quand on ne spécifie pas de nom pour les paramètres d’une fonction. Pô ma faute, chuis habitué au c++ moi :p

Utilisation

Création des sprites

Les sprites peuvent maintenant être facilement dessinés et encodés avec le logiciel Sprite Maker (reportez-vous au fichier readme de ce prog ;)).

Affichage

L’affichage n’est pas plus difficile qu’auparavant: il faut maintenant appeler drawspr(), de lui donner des coordonnées à l’écran (abscisse (ou colonne) et ordonnée (ou ligne)), de lui indiquer le sprite à afficher à cet endroit, et le mode d’affichage, grâce à l’une des 4 macros suivantes:

MODE_NOMASK_NOCLIP 
MODE_MASK_NOCLIP 
MODE_NOMASK_CLIP 
MODE_MASK_CLIP 

Pour indiquer ce sprite, il faut en fait lui fournir l’adresse en mémoire du premier élément du tableau dans lequel est enregistré le sprite en question, grâce à un pointeur.

Si ceci ne vous dit rien, sachez simplement que de manière générale le nom d’un tableau peut être utilisé comme étant justement un pointeur vers son premier élément, et que donc pour afficher un sprite enregistré dans un tableau il suffit de donner à drawsprite... le nom du tableau. ;)

Pour ceux qui ne voient toujours pas, voici un petit exemple:

  uchar sprite01[]={ ... };// code généré par Sprite Maker
  // on affiche ce sprite au point (20,10) 
  //en appliquant son masque et en gérant le clipping 
  drawspr(20,10,sprite01,MODE_MASK_CLIP); 

Bien sur ça c’est vraiment une utilisation basique, on peut également utiliser un tableau de pointeurs avec les noms de tous les sprites, comme ca chaque sprite recoit un numéro et pour afficher celui qu’on veut il suffit de connaître son numéro pour désigner le bon élément du tableau de pointeurs:

 uchar UnSprite[]={ ... };
 uchar UnAutreSprite[]={ ... };
 uchar EncoreUnSprite[]={ ... };
 uchar ToujoursUnSprite[]={ ... }; // code des sprites
 uchar * les_sprites[] =
 { UnSprite, UnAutreSprite, EncoreUnSprite, ToujoursUnSprite };
 // tableau de "pointeurs" (y'a une étoile) contenant le nom 
 // de chaque sprite, donc l'adresse vers le premier élément 
 // de chacun d'entre eux
 // affichage de EncoreUnSprite (3eme, donc n°2) sans gestion du clipping
 // -> ce sprite ne peut pas dépasser de l'écran
 drawspr(20,10,les_sprites[2],MODE_MASK_NOCLIP);
 // affichage de UnSprite (1er, donc n°0) sans appliquer son masque 
 // -> le blanc du sprite devient transparent
 drawspr(50,10,les_sprites[0],MODE_NOMASK_CLIP);

On peut également utiliser des pointeurs far pour désigner des sprites situés dans une memzone par exemple! NB: ce que j’ai décrit là est vraiment la base du C, mais j’ai pris la peine d’expliquer ça en détail parce qu’il y a beaucoup de chances pour que cette lib soient utilisée par des débutants par facilité (mais non, je ne vise personne ;p)

Idéalement chaque mode se choisit grâce à la fonction drawspr().

Pour les férus de l’optimisation, on peut également utiliser 4 fonctions différentes ayant chacune leur propre mode; ces 4 fonctions s’utilisent comme drawspr() mais sans avoir besoin de spécifer un mode, et sont:

draw_M_C(x,y,spr) -> idem que drawspr(x,y,spr,MODE_MASK_CLIP) 
draw_noM_C(x,y,spr) -> idem que drawspr(x,y,spr,MODE_NOMASK_CLIP) 
draw_M_noC(x,y,spr) -> idem que drawspr(x,y,spr,MODE_MASK_NOCLIP) 
draw_noM_noC(x,y,spr) -> idem que drawspr(x,y,spr,MODE_NOMASK_NOCLIP) 

L’ancien appel drawsprite(x,y,spr) est encore valable, et revient à écrire drawspr(x,y,spr,MODE_MASK_CLIP).

Destination

En général, afficher directement à l’écran est fortement déconseillé. Il est toujours préférable d’afficher progressivement ses dessins en buffers, c’est-à-dire quelque part en dehors de l’écran, et de faire un raffraichissement d’écran lorsque tout a été dessiné en buffers.

Les 2 “couches” qui apparaissent en mode DB sont des zones mémoire de 1024 octets situées respectivement aux segments 0x1A20 et 0x1AA0 de la mémoire video.

Par défaut, drawsprite() considère que les segments 0x1A60 (juste entre les 2 couches) et 0x1AE0 (juste derrière la 2eme) sont utilisés comme buffers. Ceci représente une certaine limitation, c’est pourquoi il est quand même possible de modifier les segments qui seront utilisés pour les buffers, mais uniquement lors de la création du programme et jamais pendant son exécution.

Deux macros sont définies dans Drawlib.h: - DRAW_BUFFER1 définit le segment du premier buffer, la valeur par défaut est 0x1A60

- DRAW_JUMP définit le nombre d’octets entre le début de chaque buffer. La valeur par défaut est 2048 puisqu’il y a les 1024 octets du buffer1 et les 1024 octets de la 2eme couche de l’écran.

Ces valeurs peuvent être modifiées au besoin, mais uniquement avant la compilation du programme. On peut donc configurer drawsprite pour afficher directement à l’écran par exemple, mais je rappelle que c’est vivement déconseillé si on veut éviter les clignotements...*

Origine des sprites

L’origine de chaque sprite se définit avant leur encodage. L’origine est le point du sprite qui sera réellement affiché en (x,y) lorsqu’on affiche le sprite en (x,y). Si l’origine est (a,b), cela revient à afficher le sprite en (x-a,y-b).

Choix des fonctions à compiler

Le fichier drawlib.h possède les 6 lignes suivantes:

#define FUNC_DRAWSPR
#define FUNC_SIZESPRITE
#define FUNC_DRAW_NOMASK_NOCLIP
#define FUNC_DRAW_MASK_NOCLIP
#define FUNC_DRAW_NOMASK_CLIP
#define FUNC_DRAW_MASK_CLIP

Chacune de ces lignes correpond à une des fonctions de la lib.

Si vous ne souhaitez pas utiliser une de ces fonctions, mettez simplement la ligne correspondante en commentaire (ne la supprimez jamais!!!) et elle sera remplacée par une fonction qui ne fait rien. Si vous souhaitez réutiliser la fonction, il suffit de retirer les commentaires de la ligne.

Notez que la fonction drawspr() utilise les 4 fonctions correspondant à chaque mode: si vous utilisez le mode mask+clip par exemple, vous ne pouvez pas mettre en commentaire la macro FUNC_DRAW_MASK_CLIP !

Cadre de clipping

Pour certains programmes (jeux ou autres), il peut être utile d’empecher drawspr() de dessiner sur une certaine zone de l’écran. Par exemple, on peut maintenant empecher de dessiner des sprites en dehors d’un cadre situé à 5 pixels du bord de l’écran.

Ceci permet par exemple de représenter une scene de jeu dans un cadre et d’afficher d’autres informations sur les côtés de ce cadre (par exemple avec les 2 autres fonctions qui n’ont pas besoin de tester le clipping).

Il n’y a plus de limitations sur les valeurs possibles, mais les limites haut et bas, gauche et droite se modifient toujours AVANT la compilation grâce aux macros (dans drawlib.h) DRAW_CLIPH, DRAW_CLIPB, DRAW_CLIPG, et DRAW_CLIPD.

Toutes les valeurs sont maintenant autorisées, du moment qu’elles sont entières et à l’intérieur de l’écran. Un sprite peut à présent dépasser de tous les côtés en même temps.

Taille des sprites

En connaissant les dimensions d’un sprite, il est parfois utile de savoir quelle place il prendra en mémoire, notamment pour le chargement à partir d’un fichier externe par exemple. La fonction sizesprite(uchar Haut, uchar Larg) renvoie le nombre d’octets que prendrait un tableau de hauteur Haut et de largeur Larg.