LES DECORS PAR IMAGES
LES DECORS PAR PUZZLE
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.
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).