Revenir au plan du site

Le double tampon pour éviter les clignotements et les cisaillements


Dans l'article précédent, si notre sprite permettait de conserver le fond, la lenteur de la routine faisait que le balayage vidéo pouvait se produire entre la restitution du fond et le nouvel affichage.
Optimiser la routine n'aurait fait que repousser le problème. On se serait toujours retrouvé limité à un positionnement sur l'écran ou un nombre de sprites maximum. Ce n'est PAS la bonne méthode.

Pour illuster le double buffer, voici une animation de la mémoire du jeu Dragon Ninja. On voit dans l'explorateur graphique qu'il utilise deux pages pour l'écran. Une page est affichée tandis que l'autre est en cours de (re)construction. Beaucoup de jeux sur Amstrad utilisent cette technique et on réalise à quel point les programmeurs étaient contraints de faire tenir toutes les données de leur jeu dans la mémoire restante, à savoir 32K seulement!

Dragon Ninja


On va adapter le source de notre chouette pour éviter les clignottements. Le principe de base est d'avoir les informations de positionnement pour chaque buffer. Ou de conserver à minima un historique pour savoir quoi effacer avant de réutiliser l'autre écran.

Le changement d'écran se fait via le registre 12 du CRTC (voir [Annexe Hardware - CRTC])
ld bc,#BC00+12 : out (c),c : ld a,#30 : inc b : out (c),a ; écran visible en #C000
ld bc,#BC00+12 : out (c),c : ld a,#20 : inc b : out (c),a ; écran visible en #8000

Jusqu'à présent, nous n'utilisions que la page #C000-#FFFF pour afficher nos dessins ce qui simplifiait les débordements de page. Comme nous allons utiliser une deuxième page graphique, il nous faut une routine qui passe à la ligne suivante quelle que soit la page utilisée. Réécrivons cette routine.
nextLineHL
ld a,h : add 8 : ld h,a ; ajouter #800 à HL
and #38 ; on teste si on déborde de la bank (passage de page+#3800 à page+#0000)
ret nz  ; pas zéro, on est toujours dans le même bloc de lignes
ld a,80  : add l : ld l,a ; on ajoute 80 (largeur d'une ligne en octets) pour passer au bloc suivant
ld a,#C0 : adc h : ld h,a ; et on enlève #4000 (additionner #C000 c'est comme enlever #4000)
ret

Note: Cette routine n'est pas un passage de ligne Universel mais elle est parfaite pour des écrans sans scrolling

Il faudra aussi que la routine qui calcule l'adresse écran ajoute la bonne page en cours. Le plus simple est de changer le tableau des lignes pour utiliser la première page. On ajoutera en fin de calcul dans le poids fort, le début de la page voulue. En mettant la page dans le poids fort de BC, nous conservons une seule addition.
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

Rendez-vous dans [ l'article suivant ] pour mettre en pratique tout ça!