Revenir au plan du site
L'affichage de sprite au XOR
Petit rappel sur les opérations logiques, en particulier celle de type
[ XOR ].
table de vérité du XOR
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
|
Le XOR est utilisé en chiffrement car son utilisation deux fois de suite avec la même valeur permet de retrouver la valeur d'origine. Cette propriété utilisée en cryptographie
peut aussi nous servir pour réaliser un affichage réversible d'un sprite!
Au lieu d'écraser les données de l'écran comme nous le faisions, nous allons effectuer un XOR entre la donnée du sprite et l'écran. C'est la seule chose qui va changer
de notre routine précédente de sprite.
ld a,(de) ; prendre l'octet de l'écran destination
xor (hl) ; faire le XOR
ld (de),a ; remettre à l'écran
inc hl : inc de ; incrémenter nos pointeurs
|
Dans cette opération cryptographique, le sprite est la clef de chiffrement. Appliquer deux fois la clef (ou le sprite) fait revenir les données à leur état initial.
Ainsi, on retrouve notre arrière plan. Seul problème, c'est moche dès que le sprite n'est pas au dessus de la couleur zéro.

Jeu Sorcery utilisant l'affichage au XOR
Le programme suivant utiliser un fond uni sur la moitié droite de l'écran et un bitmap sur la moitié gauche de l'écran, ensuite nous
allons déplacer notre sprite en X suivant la technique du
[ TRON ] que vous avez bien sûr programmé précédemment.
Ainsi on verra que tout se passe bien sur l'encre 0 mais que les effets secondaires sur du bitmap sont désagréables. Selon VOS besoins, sur un jeu comme Sorcery avec des
décors en majorité non franchissables, cette routine fait simplement le travail.
Téléchargez
[ce sprite] et
[ce fond d'écran] puis assemblez ce code source.
BUILDSNA : BANKSET 0
ORG #38 : EI : RET
ORG #100 : RUN #100
ld sp,#100 : ei
ld bc,#7F00+%10001100+%00 : out (c),c ; MODE 0
ld hl,palette : ld bc,#7F00
setPalette out (c),c : inc c : inc b : outi : ld a,(hl) : or a : jr nz,setPalette
; définir notre coordonnée X et son incrément pour faire bouger le sprite tout seul
ld hl,40 ; milieu écran en nombre d'octets
ld (positionx),hl
ld hl,1
ld (incrementx),hl
;****************
BouclePrincipale
;****************
ld bc,(positionx)
ld hl,80 ; Y=80 pour être à peu prêt centré
ld xl,9 : ld xh,36 ; dimensions du sprite largeur/lignes
ld de,donnees_sprite : call AfficheSprite
ld b,18 ; 3 frames
tempo halt : djnz tempo
; le réafficher au même endroit pour l'effacer
ld bc,(positionx)
ld hl,80 ; Y=80 pour être à peu prêt centré
ld xl,9 : ld xh,36 ; dimensions du sprite largeur/lignes
ld de,donnees_sprite : call AfficheSprite
; déplacer notre sprite
ld hl,(positionx) : ld bc,(incrementx) : add hl,bc : ld (positionx),hl
; gérer le "rebond" aux bords
ld a,h : or l : jr nz,.pasGauche : ld hl,1 : ld (incrementx),hl : .pasGauche
ld a,l : cp 79-9 : jr nz,.pasDroite : ld hl,-1 : ld (incrementx),hl : .pasDroite
jr BouclePrincipale
positionx defw 0
incrementx defw 0
AfficheSprite
; BC=coordonnée X (0-319)
; HL=coordonnée Y (0-199)
; DE=adresse des données du sprite
; XL=largeur du sprite en octets
; XH=hauteur du sprite en nombre de lignes
push de ; on met DE dans la pile car le calcul d'adresse s'en sert
call CalculeAdressePixel
pop de ; et on récupère DE
; HL=destination écran
; DE=toujours l'adresse source des données
ex hl,de ; on permute source et destination pour être utilisées
; avec l'instruction LDIR
.afficheLignes
ld b,0
ld c,xl ; chargeur la largeur d'une ligne
push de ; on met l'adresse de début de la ligne de côté
; Plus de LDIR !
.afficheXOR
ld a,(de) : xor (hl) : ld (de),a
inc hl : inc de
dec c : jr nz,.afficheXOR
pop de ; on récupère l'adresse du début de ligne
; et on calcule le passage à la ligne suivante
ex hl,de ; on permute HL et DE pour pouvoir faire des additions
ld bc,#800 : add hl,bc : jr nc,.dansLeBloc
ld bc,80-#4000 : add hl,bc ; changement de bloc!
.dansLeBloc
ex hl,de ; on permute à nouveau pour retrouver notre DE une ligne plus bas
dec xh ; notre compteur de lignes
jr nz,.afficheLignes
ret
;-------------------
CalculeAdressePixel
; BC=coordonnée X (0-159)
; HL=coordonnée Y (0-199)
; adresse de la ligne dans HL en résultat
ld de,tableau
add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2
add hl,de
ld a,(hl) : inc hl
ld h,(hl) : ld l,a
add hl,bc ; ajouter la position en OCTETS !
ret
;-------------------
adresse_ecran=#C000
largeur_ecran=80
tableau
repeat 25
repeat 8
defw adresse_ecran
adresse_ecran+=#800
rend
adresse_ecran+=largeur_ecran
adresse_ecran-=#4000
rend
palette defb #54,#56,#5C,#46,#5E,#40,#47,#43,#4E,#4B,#4C,0 ; black
donnees_sprite incbin 'hibouNoir.bin'
org #C000 : incbin 'middleForest.bin'
|

Notre hibou s'affiche proprement (enfin si on excepte le scintillement) sur le fond noir. Par contre il devient difficilement lisible quand on l'affiche sur la forêt MAIS le fond se restitue bien.
La prochaine étape va être de faire disparaitre ce scintillement en utilisant un double buffer.