LES DECORS PAR IMAGES
LES DECORS PAR PUZZLE


LES DECORS PAR IMAGES

Il s'agit dans ce cas de placer directement l'image en la copiant dans l'écran final ou l'écran de travail à partir du buffer où elle se trouve. Une simple copie suffit (Ref: Les transferts).
Cette technique est très rapide mais devient totalement inexploitable lorsque le terrain de jeu devient très grand.Il suffit de prendre l'exemple de Totalwar pour s'en convaincre.
Cette technique est à utliser seulement dans des jeux à écran fixe ou avec maximum de 4 écrans.


LES DECORS PAR PUZZLE

La technique par puzzle consiste à reconstruire un decor par morceaux ou blocks. Les différents blocks étant gardés dans une image PCX stockées en mémoire.
Les bornes d'arcade utilisent ce système pour construire l'image. A la place d'avoir un écran graphique comme on le connaît sur les ordinateurs, sa mémoire vidéo est en fait constituée de données qui réfèrent à des blocks contenus dans les roms. Ces blocks peuvent avoir plusieurs tailles mais sont de taille unique pour chaque plans. En règle générale, sur ces bornes, les blocks font 8x8 ou 16x16. C'est pour cette raison que vous avez très peu de ram mais beaucoup de roms sur ces cartes de jeux. Les consoles utilisent aussi ce principe. A la place de changer un point à l'écran sur ces machines, vous changez un "point" qui fait 8x8 ou 16x16. C'est rapide, efficace si le système est cablé en hardware.

Analyse de conception de la méthode des blocks:

Dans la figure ci-dessus, le numéro de block qui compose le debut de l'image est pris dans le tableau decor[]. Ce numéro de block désigne un endroit sur la page graphique (Buffer mémoire/image PCX). La fonction a juste ensuite à copier cet élément graphique dans l'écran de travail où dans l'écran final.
Dans Totalwar, les blocks sont de taille 32x32 points, ce qui équivaut à 10 blocks en largeur et 6 blocks de haut (Il reste 8 points). C'est la routine de scrolling qui s'occupe de placer, lignes par lignes, tous les blocks en effectuant un scrolling vertical de l'écran.
Pour connaître l'adresse de chacun des blocks par rapport à son numéro, c'est très simple. Voici le codage des blocks dans Totalwar:

Numéro de blocks dans Totalwar*

0x00 0x01 0x02 x03 0x04 0x05 0x06 0x07 0x08 0x09
0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19
0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29
0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39
0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49
0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59

(*) La version actuelle de Totalwar étend la fonction avec un pointeur sur 32 bits au lieu de 16 comme ici.

Il existe deux écrans PCX pour les décors. Ces écrans se suivent (ecran2 (128000) et ecran_load (189440)). Le deuxième est décalé de 8 lignes (8*320) pour se caler à la ligne 192 de ecran2 soit 128000+(64000-(8*320))=189440. Pöur les numéro de blocks suivants, il convient de continuer par le même principe soit : 0x60, 0x61 ....0x69, 0x70 ..., 0x79, ...0x80 ........0xA0, .....0xA9, 0xB0 jusqu'à 0xB9 pour le dernier. Il restera 16 lignes non utilisées (a voir !) en bas.

Ce codage des blocks n'est pas un simple hasard de ma part. Comme la représentation d'un octet en hexadécimal se fait sur 2 digits (quartet fort et quartet faible), on peut sans problème encoder la ligne sur le quartet fort (0xLx) et coder la colonne sur le quartet faible (0xxC) d'ou le codage 0xLC. Ce codage limite le nombre de ligne à 15 ainsi que le nombre de colonne. Si vous désirez en prendre plus en compte, utilisez un type short qui sera encodé comme suit: 0xLLCC

Pour calculer les coordonnées du blocks et donc en deduire son adresse d'offset (x+(320*y) Ref: Constitution de la mémoire écran) il suffit de se baser sur son numéro et d'appliquer quelques commandes assembleurs:

Décodage du X:

Très simple: Vous éliminez le quartet fort par un AND 0x0F, et vous multipliez le résultat par 32. Pour multiplier par 32 en binaire, decalez la donnée de 5 bits vers la gauche (SHR $5).

Décodage du Y:

Presque la même façon: Vous éliminez le quartet faible par un AND 0xF0, et vous multipliez le resultat par 320. Vous pouvez essayer, ça marche.(Note: comme le debut du quartet fort donne 32 et que ceci est la taille vertical des blocks, aucuns decalages n'est pas effectues, d'ou la simple multiplication par 320).

La fonction de copie de blocks:

void block(BYTE *ecrans,BYTE *ecrand,short xs,short ys,short ls,short hs,short xd,short yd)
{
asm volatile("
movl %0,%%esi
movl %1,%%edi
xorl %%eax,%%eax
movw %2,%%ax
addl %%eax,%%esi
movw %3,%%ax
movl $320,%%edx
mull %%edx
addl %%eax,%%esi
xorl %%eax,%%eax
movw %6,%%ax
addl %%eax,%%edi
movw %7,%%eax
movl $320,%%edx
mull %%edx
addl %%eax,%%edi
movw %4,%%cx
movw %5,%%dx
loop_block:
pushl %%esi
pushl %%edi
pushw %%cx
rep; movsb
pop %%cx
popl %%edi
popl %%esi
addl $320,%%esi
addl $320,%%edi
decw %%dx
jne loop_block

":
: "m" (ecrans),"m"(ecrand),"m"(xs),"m"(ys),"m"(ls),"m"(hs),"m"(xd),"m"(yd));

}

La fonction de copie de block en transparent:

void tblock(BYTE *ecrans,BYTE *ecrand,short xs,short ys,short ls,short hs,short xd,short yd)
{

asm volatile("
movl %0,%%esi
movl %1,%%edi
xorl %%eax,%%eax
movw %2,%%ax
addl %%eax,%%esi
movw %3,%%ax
movl $320,%%edx
mull %%edx
addl %%eax,%%esi
xorl %%eax,%%eax
movw %6,%%ax
addl %%eax,%%edi
movw %7,%%eax
movl $320,%%edx
mull %%edx
addl %%eax,%%edi
movw %4,%%cx /*largeur*/
movw %5,%%dx /*hauteur*/
loop_tblock:
pushl %%esi
pushl %%edi
pushw %%cx
loop_tblock_point:
movb (%%esi),%%al
orb %%al,%%al
je tblock_pas_point
movb %%al,(%%edi)
tblock_pas_point:
incl %%esi
incl %%edi
decw %%cx
jne loop_tblock_point
popw %%cx /*largeur block*/
popl %%edi /*destination image*/
popl %%esi /*source image*/
addl $320,%%esi
addl $320,%%edi
decw %%dx
jne loop_tblock

":
: "m" (ecrans),"m"(ecrand),"m"(xs),"m"(ys),"m"(ls),"m"(hs),"m"(xd),"m"(yd));

}

L'instruction ORB %%al,%%al teste la couleur d'index 0. Si vous voulez en utiliser une autre, mettez à la place l'instruction CMPB $<index couleur>,%%al ou "index couleur" indique la couleur a ne pas copiée.

Cette fonction est utile pour copier des zones rectangulaires d'une zone à une autre. Pour la simplicité, elle utilise la commande assembleur MUL pour multiplier y par 320. Dans la routine de sprite, il n'y a pas de multiplication par 320 avec cette instruction mais faite par une autre méthode plus rapide.

Pour construire un décor à base de blocks, il suffit donc de copier ces blocks à leurs multiples dans un écran. Vous devrez les copier au multiple de leur taille (tous les 8 pts pour des largeurs de 8, tous les 16 pts pour des largeurs de 16).


Voici des fonds en exemple qui sont utilisés dans Totalwar:

La couleur vive verte correspond à un noir non transparent. (Cet index (254) est mis en RVB a 0,0,0 aprés le téléchargement de l'image dans le programme).