Déplacement de sprite, restitution:
Maintenant qu'on sait tester une touche, on va pouvoir déplacer notre sprite.
Imaginons votre routine de sprite comme tel:
FRAME LD B,#F5 FRM IN A,(C) RRA JR NC,FRM ;on teste la VBL Coordonnee_ecran LD HL,#C020 ;notez que j'utilise des noms de label très explicites. CALL AFFICHE_SPRITE ;là bien evidement ce label saute à votre routine d'affichage LD D,5:CALL TOUCHE ;J'ai mis la routine de test de touche plus loin avec un label TOUCHE et là je teste la ligne 5 CP %01111111 ;je regarde si la touche ESPACE est pressée JP NZ,FRAME ;si ce n'est pas le cas on retourne à FRAME RET ;sinon on s'arrete là
Nous voulons déplacer notre sprite vers la droite. Ajoutons un test de touche pour cela.
Ensuite, pensons à ce que revient de déplacer un sprite vers la droite.
Cela signifie tout simplement à l'afficher 1 octet plus loin à l'écran.
Ainsi, il suffit d'incrémenter l'adresse d'affichage !!!
Nous allons utiliser les automodifications.
Comme notre adresse est stockée au label Coordonnee_ecran, il suffira d'aller modifier à cette adresse.
Mais attention: LD HL,data prend 1 octet (#21). Les octets de l'adresse sont juste après en RAM.
Il faudra donc modifier ce qui est en Coordonnee_ecran+1.
FRAME LD B,#F5 FRM IN A,(C) RRA JR NC,FRM ;on teste la VBL Coordonnee_ecran LD HL,#C020 ;adresse ou on affiche le sprite à l'écran CALL AFFICHE_SPRITE ;saute à votre routine d'affichage LD D,0:CALL TOUCHE ;la touche curseur droit sur le clavier est à la ligne 0 CP %11111101 ;c'est le bit 1 qu'il faut tester JP NZ,FRAME ;si ce n'est pas le cas on retourne à FRAME droite LD HL,(Coordonnee_ecran+1) ;on prend l'adresse contenue en Coordonnee_ecran+1 INC HL ;on incrémente l'adresse LD (Coordonnee_ecran+1),HL ;on automodifie l'adresse JP FRAME ;on retourne au début de la boucle FRAME
Bien entendu aller à gauche signifie decrementer (DEC HL) l'adresse.
Descendre revient à mettre l'adresse d'en dessous et monter, l'adresse d'au dessus (il faudra les calculer par exemple).
Restitution du fond
C'est bien gentil tout ca mais c'est moche !!!
Notre sprite se déplace, mais laisse une affreuse trainée derrière lui :(
C'est normal, quand notre sprite est affiché décalé d'un octet, le sprite précedement affiché n'est pas effacé.
Il reste donc une colonne du précédent sprite qui n'a pas été écrasée par le nouvel affichage.
Nous avons donc deux solutions:
- Avoir un fond de couleur uniforme et effacer la zone avant d'afficher notre sprite.
- Sauvegarder le fond et le ré-afficher avant le déplacement.
Pour la première solution rien de plus simple, avant d'afficher notre sprite, on remplis la zone avec des 0 par exemple (ou un autre octet si vous n'avez pas utilisé la couleur 0). Au passage, on peut utiliser un fond uniforme tramé ou répétitif ce qui sera plus original qu'un fond noir...
On se contentera donc de faire un affichage avec une valeur fixe.
Exemple:
LD A,0 ;on met un octet 0 dans A car ce sera notre couleur de fond LD HL,adresse_du_sprite_a_l_ecran ;label long mais explicite LD B,hauteur ;hauteur du sprite sprite_vide PUSH BC PUSH HL LD (HL),A ;on balance un 0 a l’écran LD E,L:LD D,H:INC DE ;on recopie HL dans DE et on incrémente l'adresse. DE contient donc HL+1 LD BC,largeur-1 ;-1 car on a déjà envoyé un octet LDIR ;on recopie les 0 POP HL CALL calcul_ligne_inferieure ;si la routine de calcul fonctionne avec HL, sinon ajoutez un EX DE,HL Avant et après le CALL POP BC DJNZ sprite_vide
A noter que la je remplis de 0 toute la zone du sprite, ce qui est idiot si vous vous déplacez d'un seul octet !!!
Il suffirait d'afficher une bande noire, d'un seul octet, à la coordonnée de votre sprite, avant de le bouger vers la droite...
Il en est de même pour les autres directions mais la bande à droite si vous allez à gauche etc etc.
Mais le plus intéressant, c'est quand même de sauvegarder le fond pour le restituer ensuite.
Pour cela il va falloir capturer le fond avant d'afficher dessus.
Le principe est simple:
Avant (ou pendant) que vous affichez votre sprite, vous récupérez les octets de l'écran avant d'afficher par dessus.
Vous stockez alors le tout quelque part en RAM.
Lorsque vous déplacerez votre sprite, vous devrez alors réafficher le fond que vous avez stocké, puis vous continuerez.
Bien entendu, il faut réflechir avant de stocker votre fond. Plusieurs solutions existent.
Vous pourrez par exemple stocker par bande, et ne ré-afficher que la bande nécessaire.
Réfléchissez bien au temps pris par votre routine car parfois tout réafficher est plus rapide que de n'afficher qu'une bande selon comment elle est stockée
Ne perdez pas de cpu inutilement...
Notez aussi que parfois, dans certains jeux la solution d'avoir le fond quelque part en mémoire avec rien dessus a été retenue.
Ce n'est pas forcément une mauvaise solution si vous avez beaucoup de RAM disponible. Encore une fois il faut calculer.
Vous pourrez aussi par exemple sauvegarder le fond à une adresse, puis récupérer les valeurs grâce à la pile (donc par groupe de 2 octets) afin de gagner du temps.
Il y a donc beaucoup de possibilité en fonction du besoin et des contraintes.
Beaucoup d'astuces aussi à trouver. Mais je vous laisse y réfléchir.