Revenir au plan du site

Exemple de double buffer avec notre hibou


Avec le source suivant, vous devrez voir le hibou se déplacer de façon fluide et sans glitch visuel.


Nous réutilisons nos deux fichiers [hibou] et [forêt]
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
;****************
call waitVBL ; on attend d'être sûr que l'écran précédent soit complètement affiché
ld bc,#BC00+12 : out (c),c : ld a,#30 : inc b : out (c),a ; écran visible en #C000
; si restorex8 vaut 255 c'est le premier affichage, il ne faut pas 'restituer'
ld b,#80 : ld a,(restorex8) : cp 255 : jr z,.first8 : ld c,a : call AfficherHibou : .first8
ld b,#80 : ld a,(positionx) : ld (restorex8),a : ld c,a : call AfficherHibou
call DeplacerHibou
;
call waitVBL ; on attend d'être sûr que l'écran précédent soit complètement affiché
ld bc,#BC00+12 : out (c),c : ld a,#20 : inc b : out (c),a ; écran visible en #8000
; si restorexC vaut 255 c'est le premier affichage, il ne faut pas 'restituer'
ld b,#C0 : ld a,(restorexC) : cp 255 : jr z,.firstC : ld c,a : call AfficherHibou : .firstC
ld b,#C0 : ld a,(positionx) : ld (restorexC),a : ld c,a : call AfficherHibou
call DeplacerHibou

jr BouclePrincipale

DeplacerHibou
; 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
ret

AfficherHibou
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
ret

restorex8 defb 255 ; il ne faut pas restituer le fond la première fois
restorexC defb 255 ; il ne faut pas restituer le fond la première fois
positionx defw 0
incrementx defw 0


waitVBL ld b,#F5
.loop in a,(c) : rra : ret c : jr .loop

AfficheSprite
; BC=page + coordonnée X (0-79)
; 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
; notre routine de passage à la ligne suivante, adaptée pour DE
ld a,d : add 8 : ld d,a ; ajouter #800 à DE
and #38 ; on teste si on déborde de la bank (passage de page+#3800 à page+#0000)
jr nz,.nextLine ; pas zéro, on est toujours dans le même bloc de lignes
ld a,80  : add e : ld e,a ; on ajoute 80 (largeur d'une ligne en octets) pour passer au bloc suivant
ld a,#C0 : adc d : ld d,a ; et on enlève #4000 (additionner #C000 c'est comme enlever #4000)
.nextLine
dec xh ; notre compteur de lignes
jr nz,.afficheLignes
ret
;-------------------
CalculeAdressePixel
; B=page vidéo #00, #40, #80 ou #C0
; C=coordonnée X (0-79)
; 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 X en octets et la page!
ret
;-------------------
adresse_ecran=#0000
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'

; initialiser notre écran sur les deux pages!
org #8000 : incbin 'middleForest.bin'
org #C000 : incbin 'middleForest.bin'