Sauvegarder l'arrière plan pour le restituer plus tardLa méthode du XOR est pratique et plutôt rapide mais c'est moche dès lors qu'il y a un arrière plan. Il faut donc choisir une méthode pour restituer le fond après le passage d'un sprite.Une des techniques est de sauvegarder dans un tampon (de la taille du sprite), le fond de l'écran à l'endroit même où l'on va afficher le sprite. Pour sauvegarder le fond, nous calculerons l'adresse écran et au lieu de lire les données puis écrire dans l'écran, nous ferons l'inverse. Lire l'écran et écrire dans le tampon. La restitution du fond pourra se faire avec la routine de sprite classique, en lui donnant l'adresse du tampon de sauvegarde plutôt que celle du sprite. Quand on veut afficher le hibou, c'est toujours la même valeurqui est envoyée, sinon on met dans DE le tampon et on appelle RestituerTampon. C'est vraiment histoire de raccourcir un peu le source. AfficherHibou ld de,donnees_sprite RestituerTampon ; nécessite DE pré-positionné ld hl,80 ; Y=80 pour être à peu prêt centré ld xl,9 : ld xh,36 ; dimensions du sprite largeur/lignes call AfficheSprite retAu final, nous voyons que chaque amélioration se paie (ici au prix fort) car si avec la méthode XOR, on ne passait que deux fois au même endroit. Ici, il faut restituer puis sauvegarder et enfin afficher, nous faisons maintenant 3 passages au même endroit. ; restitution, sauvegarde, affichage ld b,#80 : ld a,(restorex8) : cp 255 : jr z,.first8 : ld c,a : ld de,backup8 : call RestituerTampon : .first8 ld b,#80 : ld a,(positionx) : ld de,backup8 : call SauvegarderPortionEcran ld b,#80 : ld a,(positionx) : ld (restorex8),a : ld c,a : call AfficherHibouToujours pour raccourcir un peu notre source, au lieu de sauvegarder/restituer DE avec PUSH DE et POP DE avant le calcul de l'adresse écran, on va changer l'addition dans la routine CalculeAdressePixel ld de,tableau add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2 add hl,deLe code d'addition est plus lent mais sans avoir à faire PUSH/POP, on gagne du temps machine au global ;) CalculeAdressePixel add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2 ld a,lo(tableau) : add l : ld l,a ld a,h : adc hi(tableau): ld h,aSource d'exemple, nous utilisons [hibou] et [forêt] BUILDSNA : BANKSET 0 ORG #38 : EI : RET ORG #100 : RUN #100ld 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 : ld de,backup8 : call RestituerTampon : .first8 ld b,#80 : ld a,(positionx) : ld c,a : ld de,backup8 : call SauvegarderPortionEcran 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 : ld de,backupC : call RestituerTampon : .firstC ld b,#C0 : ld a,(positionx) : ld c,a : ld de,backupC : call SauvegarderPortionEcran 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 de,donnees_sprite RestituerTampon ; nécessite DE pré-positionné ld hl,80 ; Y=80 pour être à peu prêt centré ld xl,9 : ld xh,36 ; dimensions du sprite largeur/lignes call AfficheSprite ret waitVBL ld b,#F5 .loop in a,(c) : rra : ret c : jr .loop SauvegarderPortionEcran ld hl,80 ; Y=80 pour être à peu prêt centré ld xl,9 : ld xh,36 ; dimensions du sprite largeur/lignes ; BC=page + coordonnée X (0-79) / HL=coordonnée Y (0-199) / DE=adresse du tampon de sauvegarde ; XL=largeur du sprite en octets / XH=hauteur du sprite en nombre de lignes call CalculeAdressePixel ; HL=source écran ; DE=tampon de sauvegarde ld b,0 .sauvegardeLignes ld c,xl ; chargeur la largeur d'une ligne push hl ; on met l'adresse de début de la ligne de côté ldir pop hl ; on récupère l'adresse du début de ligne ; et on calcule le passage à la ligne suivante 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) jr nz,.nextLine ; 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) .nextLine dec xh ; notre compteur de lignes jr nz,.sauvegardeLignes ret ; ------------------------------- 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 call CalculeAdressePixel ; 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 ld b,0 .afficheLignes ld c,xl ; chargeur la largeur d'une ligne push de ; on met l'adresse de début de la ligne de côté ldir 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 add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2 ld a,lo(tableau) : add l : ld l,a : ld a,h : adc hi(tableau): ld h,a 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,#4D,#4E,#4B,#4C,0 ; Rose donnees_sprite incbin 'hibouRose.bin' 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 backup8 defs 9*36 ; on réserve la place de sauvegarde pour notre sprite backupC defs 9*36 ; on réserve la place de sauvegarde pour notre sprite ; initialiser notre écran sur les deux pages! org #8000 : incbin 'foret8couleurs.bin' org #C000 : incbin 'foret8couleurs.bin' Notre hibou se déplace sur toutes les portions de l'écran, par contre, il n'est pas détouré. Rendez-vous dans [ l'article suivant ] pour traiter la transparence des sprites purement logiciels Roudoudou CPCrulez[Content Management System] v8.732-desktop/c Page créée en 099 millisecondes et consultée 32 foisL'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko. |
|