CODING ★ COURS DE GRAPHISME ANIMATION MULTI-SPRITES ★

Graphic - 16 - Animation Multi - Sprites|SOS Programmeurs)

CHAPITRE 1 : CREATION DES TABLES DE GESTION ET SOUS ROUTINES

Installez vous confortablement car cette suite de  chapitres  sera plutôt  longue et les listings bien garnis .  Les principes de bas sont assez simples mais leur application demande beaucoup de programmation .

Tout d'abord posons le  problème  de  l'animation successive de plusieurs sprites :

La première chose qui vient à  l'esprit concerne les coordonnées écran de ceux-ci , VISAD et COINBD  seront  différents  pour  chaque dessin à afficher donc modifiés à chaque  changement  de  dessin  et  il  faudra donc garder en mémoire les adresses d'affichage de tous les  sprites en cours . Il n'est pas non plus question de voir tout l'ensemble se déplacer dans une même direction alors il faudra aussi mémoriser le sens de déplacement de chacun d'eux . Nous avons conservé le nom de DIRJOY pour  cet  octet bien que le joystick n'entre pas en jeu dans nos exemples .

Ceci va nous conduire  à  créer  une  table  de  données qui permettra de stocker en permanence ces 2  informations  et le programme fonctionnera comme ceci :
 

1 : On prend les adresses d'affichage  du  1er sprite dans la table ainsi que la direction dans laquelle il se deplace .
2 : On calcule le déplacement .
3 : On met  les  nouvelles  adresses  d'affichage  dans  la table pour le  prochain tour .
4 : On affiche le sprite .
5 : On pointe  sur  les  adresses  d'affichage  du  sprite  suivant et on  recommence en 2
6 : Quand toute la série des sprites à été affichée on recommence en 1 .
Puisque nous devons obligatoirement utiliser  une table de mémorisation ,  faisons les choses  à  fond  en  l'utilisant  pour  gagner  du  temps lors de  l'exécution du programme . On ajoute  2  octets  à cette table qui contiendra l'adresse des  données  de  chaque  sprite  ,  on  économisera  ainsi l'appel traditionnel à FINDSP ce qui est un gain appréciable .

Pour des applications plus sophistiquées ,  un octet nommé STATSP sera le bienvenu . Son contenu nous dira  si  le  sprite en cours exige un traitement particulier ou non . Bien que  nous  ayons  déjà stocké l'adresse du sprite , conserver aussi son numéro NUMSP sera utile lorsque nous aborderons les tests de collision . Ce numéro permettra en  effet de savoir rapidement quel sprite
 rencontre quel autre .

 Pour conclure , on ajoute encore 2  octets  , HSP et LSP qui contiendront les dimensions du sprite en cours .  Ces 2 données étant invariables dans nos exemples ils ne seront jamais utilisés mais imaginez que les sprites utilisés soient de taille  différente  et  cela  devient  indispensable  .  Mieux vaut prévenir que guérir ...

Si nous avons bien compté , il faudra  réserver une zone de 11 octets par sprite qui contiendra dans l'ordre :
 

 

ADSP1   DW 0 ;Adresse du 1er sprite (2 octets)
 VISAD1  DW 0 ;Adresse d'affichage du 1er sprite (2 octets)
 COINBD1 DW 0 ;Coin oppose en bas a droite 1er du sprite (2 octets)
 DIRJOY1 DB 0 ;Direction du 1er sprite (1 octet)
 STATSP1 DB 0 ;Etat du 1er sprite (1 octet)
 NUMSP1  DB 0 ;Numero du 1er sprite necessaire pour certains tests (1 octet)
 HAUTSP1 DB 0 ;Taille du 1er sprite . 2 octets inutilises dans nos exemples .
 LENSP1  DB 0
 ;
 ADSP2   DW 0 ;Adresse du 2ème sprite (2 octets)
 VISAD2  DW 0 ;Adresse d'affichage du 2ème sprite (2 octets)
 COINBD2 DW 0 ;Coin oppose en bas a droite du 2ème sprite (2 octets)
 DIRJOY2 DB 0 ;Direction du 2ème sprite (1 octet)
 STATSP2 DB 0 ;Etat du 2ème sprite (1 octet)
 NUMSP2  DB 0 ;Numero du 2ème sprite necessaire pour certains tests (1 octet)
 HAUTSP2 DB 0 ;Taille du 2ème sprite . 2 octets inutilises dans nos exemples .
 LENSP2  DB 0
 ;

Etc .......


Cela nous fera pour 25 sprites  ,  25*11  octets  soit 275 octets . Il ne reste plus pour gérer cette table qu'à  créer un pointeur 16 bits POINTSP qui mémorisera en permanence le  début  de  l'un  des  25  zones  de  11 octets à utiliser .

Pour la gestion de  ces  tables  ,  on  pourrait prélever directement les données à partir de ce pointeur mais  ce  type  de gestion est plutôt lourd .
Nous avons plus élégant à proposer :

On rajoute une zone de  11  octets  (Encore  !)  ces 11 octets seront les seuls directement accessibles par les routines  d'animation du programme . Il suffira de pointer dans  la  table  de  275  octets  la  zone  de 11 octets à utiliser par le programme et de la recopier par LDIR . Lorsque tout sera fini , on prendra la zone des  11  octets  du  programme  pour la remettre dans la table comme ceci :

1 : Pointer la zone de 11 octets table voulue .
2 : La copier par LDIR dans les 11 octets programme .
3 : Memoriser le pointeur .
4 : Déplacer , animer , tester ,  etc  ... Aura pour effet de modifier le  contenu des 11 octets programme sans toucher aux 11 octets table .
5 : On recopie par LDIR dans la zone table les 11 octets programmes mis à  jour .
 Reste une décision à prendre : Comment  initialiser la table ? On peut y- placer directement les données en écrivant directement en RAM .
 

     Ex : ADSP1   DW #9C44
          VISAD1  DW #C000
          COINBD1 DW #D053
          DIRJOY1 DB %0101
          STATSP1 DB #FF
          NUMSP1  DB 1
          HAUTSP1 DB 0
          LENSP1  DB 0
 ;
          ADSP2   DW #9D50
          VISAD2  DW #D034

          ETC ...


Non seulement c'est fastidieux mais  de  plus  difficile à modifier et de surcroît il faudrait calculer préalablement  toutes  les valeurs ce qui n'est pas vraiment simple !

On préfèrera créer des tables qui initialiseront la table , cela prend de la place en RAM et impose une section d'initialisation assez longue mais à le mérite de laisser le  soin  des  calculs  à  votre  CPC  . Vous pourrez aussi modifier rapidement une valeur qui ne vous plait pas !

Nous ajouterons la table : LISTSP qui  contiendra une suite de 25 numéros de sprites correspondant à ceux  que  l'on  veut  voir  à l'écran . ADSP sera calculée depuis ce numéro .

LISTDIR : 25 octets  où  l'on  mettra  les  25  directions d'origine pour chaque sprite .

LISTSTA : 25 octets de statut  pour  les  sprites  ,  tous à #FF dans nos exemples .

LISTADV : 50 octets qui détermineront la 1ère position d'affichage des 25 sprites . COINBD sera calculé d'après cette valeur .

La section de programme qui  effectue  la  recopie  de ces octets dans la zone sprites sera une excellente occasion  de revoir les systèmes d'adressage du cours assembleur de SOS5 .

Le programme qui suit  déplace  successivement  25  sprites  et impose un changement de direction lorsque l'un  d'entre  eux  touche  la bordure . Pour déterminer  la  nouvelle  direction   ,   nous   avons  utilisé  une  routine d'interruption en détournant le  vecteur  #38  vers  une  routine créée à cet effet . La mise en oeuvre est  des  plus  simple  ,  au lieu de mettre un RET  (#C9) en #38 , on met l'adresse 16bits de  la routine à exécuter en #39 et le cycle d'interruption ne se souciera plus que de notre routine .

 La  routine  COMPTE  est  extrèmement   simple  puisqu'elle  se  contente d'incrémenter régulièrement un compteur de 0  à  25 et de recommencer dès que le maximum de 25 est atteint . Ce  qu'il  faut en revanche savoir , c'est que cette routine est activée tous les 1/300s. et ceci QUOIQUE FASSE LE PROGRAMME PRINCIPAL ! Ce qui  revient  à  dire  que  les  registres  qu'elle emploie se retrouvent modifiés . Ainsi :

LD A,12
LD (CASE),A
Le cycle d'interruption peut se  déclencher  entre  ces 2 instructions et dans ce cas , ce n'est pas 12  qui  sera chargé dans CASE mais la valeur mise dans A par la routine sous interruption  COMPTE . Il faut donc impérativement préserver tous les registres utilisés par COMPTE et les restituer en sortie . De plus toute routine appelée par  un cycle d'interruption doit commencer par DI et se finir par EI  ce  qui  évite qu'une routine d'interruption soit elle même interrompue par une autre ...

Dernier détail , lorsque  vous  mettez  au  point  un programme utilisant cette astuce  ,  pensez  à  prévoir  un  point  de  sortie  qui  restaure les interruptions ou alors , ne mettez ces  routines  en place qu'en dernier ! Un retour au basic  ou  dans  un  programme  assembleur  avec  les interruptions bloquées ou détournées est assez peu désirable !

CHAPITRE 2 : 1ER PROGRAMME SECTION INITIALISATION

Voici enfin le  programme  promis  !  Les  sous  routines et  la section initialisation sont communes à  tous  les  exemples  ultérieurs  , vous ne la reverrez plus dans les exemples suivants .

 

;
 ;- ANIM3.MAX  -
 ;
 ;- 1 / Animation automatique de 25 sprites -
 ;- Tests de sortie d'ecran et changement de direction si sortie d'ecran -
 ;- Utilise une table en mode 0 ou TOUS LES SPRITES SONT DE TAILLE IDENTIQUE -
 ;
         ;ORG 35000
         ;JP DEBUT
 ;
 ;- Section EQUate -
 ;
 HSP     EQU #0A04             ;  ;Largeur & hauteur du sprite
 HSP1    EQU #0903             ;  ;Largeur-1 & hauteur-1 du sprite
 HSP2    EQU #0A               ;  ;Hauteur du sprite
 LSP     EQU 4                  ; ;Largeur du sprite
 LSP1    EQU 3                  ; ;Largeur-1 du sprite
 TOTSP   EQU 40                ;  ;Nombre d'octets par sprite
 NBSP    EQU 27                ;  ;Nombre de sprites
 TABLSP  EQU 40000             ;  ;Adresse de chargement de la table
 ADINK   EQU NBSP*TOTSP+TABLSP+4 ;Formule qui donne la table des encres
 ;
 NBTOANI EQU 25 ;Nombre de sprites a animer
 ;
 ;- Section variables -
 ;
 ADPROV  DW 0  ;Adresse écran provisoire pour diagonale
 OLDADV  DW 0  ;Adresse écran avant deplacement
 OLDCOIN DW 0  ;Memorisation de COINBD
 OLDVISU DW 0  ;Memorisation de VISAD
 POINTSP DW 0  ;Memorisation de l'adresse des parametres du sprite en cours
 ;
 ;- Parametres du sprite en cours (11 octets) -
 ;
 ADSP    DW 0 ;Adresse du sprite choisi
 VISAD   DW 0 ;Adresse d'affichage du sprite choisi
 COINBD  DW 0 ;Coin oppose en bas a droite du sprite choisi
 DIRJOY  DB 0 ;Direction du sprite en cours
 STATSP  DB 0 ;Etat du sprite
 NUMSP   DB 0 ;Numero du sprite necessaire pour certains tests
 HAUTSP  DB 0 ;2 octets inutilises ici . Si l'on utilise une table ou les
 LENSP   DB 0 ;sprites sont de taille differente on y mettra les dimensions
 ;           ; ;du sprite en cours
 ;
 ;- Table de gestion de 25 sprites a animer , 11 octets par sprite -
 ;
 LIST
 ZONESPT DS 275  ;275 octets pour la table de gestion des sprites
 NOLIST
 ;
 ;- Tables pour initialisation de la table des 25 sprites a animer -
 ;
 LISTSP  DB 01,02,01,03,04,05,06,07,08,09,10,11,12,13,14,14,15,18,18,19,20,20
         ;DB 21,21,22
 LISTDIR DB %1010,%1000,%0110,%1010,%0010,%1010,%0110,%0010,%0110,%0010
         ;DB %1001,%0101,%0110,%0010,%0100,%0010,%0101,%0101,%1001,%0101
         ;DB %0001,%1000,%0100,%1000,%0101
 LISTSTA DB #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
         ;DB #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
         ;DB #FF,#FF,#FF,#FF,#FF
 LISTADV DW #C010,#E842,#D876,#F893,#C0A5,#C0C7,#F0C1,#C032,#F0A4,#C145
         ;DW #E145,#C184,#E940,#E987,#C1A9,#F1D8,#C240,#E278,#F284,#FB15
         ;DW #C422,#CCA1,#C46A,#DCBF,#C500
 ;

     Ici figurent  les  sous  routines  essentielles  qu'utiliseront  tous nos  exemples .

 ;
 ;- Sous routines specifiques a l'animation multi sprites -
 ;
 ;Remettre le pointeur au  debut  de  la  table  gestion  et initialiser le
 ;compteur de boucle B
 INIANIM LD HL,ZONESPT    ;Pointer sur le debut de la table gestion
         ;LD (POINTSP),HL  ;et ranger le pointeur
         ;LD B,NBTOANI     ;Nombre a afficher
         ;RET
 ;
 ;- Copier 11 octets de la table gestion dans la zone programme -
 ;
 TRANSP  PUSH BC          ;Passer les parametres du sprite au programme
         ;LD HL,(POINTSP)  ;Recopier la zone pointee dans la zone
         ;LD DE,ADSP       ;de 11 octets utilisable par le programme
         ;LD BC,11
         ;LDIR             ;;Apres LDIR , HL pointe sur le 1er octet de la zone
         ;LD (POINTSP),HL  ;de 11 octets suivante , il est donc pret a
         ;POP BC           ;;l'emploi .
         ;RET
 ;
 ;- Copier les 11 octets de la zone programme dans la zone table gestion -
 ;
 ;Il faut noter que  cette  routine  est  TOUJOURS  appelee  apres TRANSP , le
 ;pointeur POINTSP pointe donc la zone suivante  . Pour remettre les donnees a
 ;la meme place dans la table de gestion  ,  on reculera ce pointeur de 1 pour
 ;viser le dernier octet de la zone de  11  et on fera le transfert du dernier
 ;vers le 1er octet avec LDDR .
 ;
 SPTRANS PUSH BC          ;Ranger les nouveaux parametres du sprite
         ;LD DE,(POINTSP)  ;dans la table
         ;DEC DE
         ;LD BC,11
         ;LD HL,LENSP
         ;LDDR
         ;POP BC
         ;RET
 ;
 ;- Routine pour changement de direction -
 ;
 ;La valeur du compteur variera tous les 1/300s. La routine CHDIR pointera sur
 ;le 1er octet de la liste des  25  directions utilisees et ajoutera la valeur
 ;du compteur a ce pointeur ce  qui  permettra de fixer une nouvelle direction
 ;de maniere sinon aleatoire mais du moins difficilement previsible .
 ;
 COMPTE  DI           ; ;L'incrementation de ce compteur est provoque
         ;PUSH AF       ;par le detournement du vecteur #38 des interruptions
         ;LD A,(CPTDIR) ;du Z80 .
         ;INC A
         ;CP 26
         ;JR C,NORAZD
         ;XOR A
 NORAZD  LD (CPTDIR),A
         ;POP AF
         ;EI
         ;RET
 ;
 CHDIR   LD A,(CPTDIR) ;Change la direction du sprite en cas de necessite
         ;LD HL,LISTDIR ;Adresse de deépart de la table des directions
         ;LD B,0        ;possibles a laquelle on ajoute la valeur donnee
         ;LD C,A        ;par le cycle d'interruptions
         ;ADD HL,BC
         ;RET
 ;
 CPTDIR  DB 0   ;Contiendra valeur de 0 a 25 donnee par le cycle d'interruption
 ;
 AD38    DB 0
 ADR39   DW 0
 ;
 ;Ici commence le programme proprement dit .
 ;
 ;- Initialiser encres -
 ;
 DEBUT   LD HL,ADINK  ;Adresse des encres table de sprites donnee par EQU
         ;XOR A
 FIXINK  INC A        ;Initialiser les encres
         ;LD B,(HL)
         ;LD C,(HL)
         ;BIT 7,B
         ;JR NZ,FININK
         ;PUSH AF
         ;PUSH HL
         ;CALL #BC32
         ;POP HL
         ;INC HL
         ;POP AF
         ;JR FIXINK
 ;
 ;- Ranger les adresses des sprites , leur direction et leur statut -
 ;
 FININK  LD IX,ZONESPT ;Adresse table gestion des sprites
         ;LD IY,LISTSP  ;Adresse des numéros a animer
         ;LD B,NBTOANI  ;Nombre a animer
 ;
 FINDSP  LD A,(IY+0)    ;Numero du sprite demande
         ;LD (IX+8),A    ;Ranger
         ;LD HL,TABLSP+4 ;TABLSP+4 est l'adresse ou commence le 1er sprite
 ;                     ; ;Defini par EQU
 LOOKSP  DEC A          ;Ceci est l'equivalent de FINDSP adapte au besoin
         ;JR Z,ESTFIND   ;de ce programme .
         ;LD DE,TOTSP   ;Nombre d'octets occupes par 1 sprite defini par EQU
         ;ADD HL,DE     ;Pointer le debut du suivant
         ;JR LOOKSP
 ;
 ESTFIND LD (IX+0),L   ;Ranger l'adresse de visualisation dans la table
         ;INC IX        ;en pensant a l'inversion LSB/MSB
         ;LD (IX+0),H
         ;INC IX        ;Pointer 11 octets plus loin dans la table
         ;INC IX        ;pour le sprite suivant
         ;INC IX
         ;INC IX
         ;INC IX
         ;LD A,(IY+25)  ;Octet direction
         ;LD (IX+0),A   ;ranger
         ;INC IX
         ;LD A,(IY+50)  ;Octet statut
         ;LD (IX+0),A   ;ranger
         ;INC IX
         ;INC IX
         ;INC IX
         ;INC IX
         ;INC IY
         ;DJNZ FINDSP
 ;
 ;- Ranger les adresses visu et coinbd -
 ;
         ;LD IX,ZONESPT+2 ;Adresse table gestion des sprites pour VISAD
         ;LD IY,LISTADV   ;Adresses de 1er affichage
         ;LD B,NBTOANI    ;Nombre a animer
 ;
 NXTADV  LD L,(IY+0)  ;Prendre adresse visu dans la table LISTAD
         ;INC IY
         ;LD H,(IY+0)
         ;INC IY
         ;LD (IX+0),L  ;On range VISAD dans la table de gestion
         ;INC IX
         ;LD (IX+0),H
         ;INC IX
 ;
 FINDCOIN PUSH BC      ;On calcule COINBD pour chaque sprite
         ;LD BC,HSP1
 ;
         ;PUSH BC
         ;LD B,0
         ;ADD HL,BC
         ;POP BC
 COIN    CALL ADINF
         ;DJNZ COIN
         ;POP BC
 ;
         ;LD (IX+0),L   ;On le range
         ;INC IX
         ;LD (IX+0),H
         ;INC IX        ;et on pointe sur la suite
         ;INC IX
         ;INC IX
         ;INC IX
         ;INC IX
         ;INC IX
         ;INC IX
         ;INC IX
         ;DJNZ NXTADV
 ;

STOP CONSEIL ! Si vous modifiez ce listing ou en écrivez un autre , ne  rédigez que cette section du programme , mettez  un  RET ici , et listez la mémoire à partir de l'adresse  ZONESP pour voir si les paramètres sont corrects et aux bons endroits dans la  table  ! L'erreur la plus courante est d'inverser poids fort et poids faible dans un adressage 16 bits !

CHAPITRE 3 : SECONDE PARTIE DU 1ER PROGRAMME

On commence par attendre un peu puis on modifie le vecteur d'interruption du Z80 . Ceci fait on affiche nos 25  sprites pour la 1ère fois . Pour ce 1er affichage , la direction est remise à  0 car aucun déplacement n'a encore été effectué et ADPROV  ,  OLDADV  ne  sont  pas  initialisées  .  Faute de cette précaution , la sortie  de  AFFISP  mettrait  une  série  de  0 dans une zone  stratégique du CPC .

 ;
         ;LD BC,#4000
 WAITCOU DEC BC        ;Attendre un peu avant de bloquer les interruptions
         ;LD A,B
         ;OR C
         ;JR NZ,WAITCOU
 ;
 MODI38  DI           ; ;Annuler detourner le cycle normal des interruptions
         ;LD HL,(#39)   ;vers la routine COMPTE
         ;LD (ADR39),HL
         ;LD HL,COMPTE
         ;LD (#39),HL
         ;LD A,(#38)    ;Sauver le contenu originel de la case #38
         ;LD (AD38),A
         ;EI
 ;
 ;- Effectuer 1er affichage -
 ;
         ;CALL INIANIM  ;Retour ,HL pointe ADSP , B=Nombre a animer et
 NXTAFF  PUSH BC       ;HL est copie dans POINTSP
         ;CALL TRANSP   ;Copie 11 octets sprite en zone prog.et avance pointeur
         ;XOR A         ;;Mettre direction a 0 pour affichage
         ;LD (DIRJOY),A
         ;CALL AFFISP   ;Afficher
         ;POP BC
         ;DJNZ NXTAFF
 ;

On commence la boucle d'animation par le test de SPACE .
 

 ;
 ;- Boucle d'animation des 25 sprites -
 ;
 RECOM   DI           ; ;Test direct de SPACE presse
         ;PUSH BC
         ;LD BC,#F792
         ;OUT (C),C
         ;LD BC,#F645
         ;OUT (C),C
         ;LD B,#F4
         ;IN A,(C)      ;SPACE ? Oui si #7F
         ;EI
         ;CP #7F
         ;POP BC
         ;JR NZ,NOQUIT
 ;
         ;DI
         ;LD HL,(ADR39)  ;Si SPACE presse restaurer interruptions
         ;LD (#39),HL    ;et fini
         ;LD A,(AD38)
         ;LD (#38),A
         ;EI
         ;RET
 ;
 NOQUIT  CALL INIANIM ;Remettre pointeur en debut de ZONESP et compteur a 25
 ;
 ;- Boucle pour deplacer un sprite -
 ;
 NXTANIM CALL TRANSP     ;Passer les parametres du sprite en cours
         ;PUSH BC         ;;au programme
 ;
         ;LD HL,(VISAD)   ;Recopier les adresses initiales pour pouvoir
         ;LD (OLDVISU),HL ;annuler un mouvement prevu mais impossible .
         ;LD HL,(COINBD)
         ;LD (OLDCOIN),HL
 ;
         ;LD A,(DIRJOY)   ;Si DIRJOY=0 le sprite est temporairement coince
         ;JR Z,NOAFF      ;on ne le reaffiche donc pas .
 ;
         ;DI             ; ;Mettre le cycle d'interruption en route faute de
         ;PUSH AF         ;;quoi , COMPTE qui determine le changement de
         ;LD A,(AD38)     ;direction serait inactif et les sprites resteraient
         ;LD (#38),A      ;coinces en fin de course !
         ;POP AF
         ;EI
 ;
         ;RRC A           ;;Routines de deplacement comme dans SOS6
         ;PUSH AF         ;;Si le changement de direction est invalide
         ;CALL C,ENHAUT   ;apres l'un des 4 CALL on resortira en NXTVERT
         ;POP AF          ;grace a un petit tripotage du pointeur de pile .
 ;
         ;RRCA
         ;PUSH AF
         ;CALL C,ENBAS
         ;POP AF
 ;
         ;RRCA
         ;PUSH AF
         ;CALL C,AGAUCH
         ;POP AF
 ;
         ;RRCA
         ;PUSH AF         ;;Ce PUSH et POP semble inutile mais il ne faut pas
         ;CALL C,ADROIT   ;oublier que le pointeur de pile peut-etre manipule
         ;POP AF          ;par les tests . Il convient donc de conserver la
 ;                     ;  ;meme structure de pile .
 ;
         ;DI             ; ;On a plus besoin du cycle d'interruption
         ;LD A,#C9        ;donc on l'annule par un code RET jusqu'au
         ;LD (#38),A      ;prochain tour cela accelerera l'affichage .
         ;EI
 ;
         ;CALL AFFISP     ;Afficher a la nouvelle position
 NXTVERT CALL SPTRANS    ;et recopier les nouvelles coordonnees dans la table
 NOAFF   POP BC          ;des sprites
         ;DEC B
         ;JP NZ,NXTANIM   ;Sprite suivant
         ;JP RECOM        ;On recommence une serie de 25
 ;

Voila pour le corps principal du programme  qui n'a rien de bien complexe :

Pour les tests de sortie  d'écran  ,  seule  la  section  de sortie en cas de  rencontre avec le bord de  l'écran  change  un  peu  .  Au lieu de bloquer le  sprite , on active la routine qui le renvoie dans une autre direction .

 ;
 ;- En bas -
 ;
 ENBAS   LD B,4         ;;Comme dans SOS6
         ;LD HL,(COINBD)
 ;
 B1      LD A,H
         ;SUB #FF
         ;JR NZ,OKBAS
         ;LD A,L
         ;CP #80
         ;JR NC,STOPBAS
 ;
 OKBAS   CALL ADINF
         ;DJNZ B1
 ;
         ;LD (COINBD),HL
 ;
         ;LD HL,(VISAD)
         ;LD (ADPROV),HL
         ;LD B,4
 B2      CALL ADINF
         ;DJNZ B2
         ;LD (VISAD),HL
         ;SCF
         ;RET
 ;

        Ici ça change nettement par  rapport  aux précédentes versions . Noter que CHDIR renvoie une nouvelle direction dans HL sans tester sa validité ! Il est donc  possible  qu'il  renvoie  un  mouvement  impossible  auquel  cas on recommence tout . Quand la nouvelle  direction est trouvée la manipulation du pointeur de pile renvoie en NXTVERT sans  rien  afficher  , dans le cas ou le  sprite se trouve dans un angle  ,  CHDIR peut renvoyer une direction invalide pour le prochain tour de boucle !  Dans  ce  cas  , on verra l'un des sprites s'arrèter un bref instant .  Ce  n'est  pas  très élégant mais très suffisant pour mettre en évidence  le  principe  essentiel  .  Nous  vous montrerons de meilleures méthodes par la suite .

 ;
 STOPBAS CALL CHDIR    ;On ne peut plus descendre donc on cherche une nouvelle
         ;LD A,(HL)     ;direction . Un eventuel bit mis vers le bas par CHDIR
         ;AND %11111101 ;est enleve par AND . Si ce AND renvoie 0 on recommence
         ;JR Z,STOPBAS  ;jusqu'a ce que CHDIR renvoie une direction acceptable.
 ;
 NEWDIR  LD (DIRJOY),A ;Sortie commune aux 4 changements de direction
         ;POP IY        ;On enleve une adresse de la pile pour CALL C,direction
         ;POP IY        ;et encore une pour le PUSH AF qui precede CALL C
         ;LD HL,(OLDVISU) ;On annule toute eventuelle modification de position
         ;LD (VISAD),HL   ;et la pile ayant ete reequilibree par les 2 POP IY
         ;LD HL,(OLDCOIN) ;on saute directement en NXTVERT pour passer au
         ;LD (COINBD),HL  ;sprite suivant .
         ;JP NXTVERT
 ;

Les 3 autres tests sont similaires .
 

;
 ;- Mouvement en haut -
 ;
 ENHAUT  LD HL,(VISAD)
         ;LD B,4
 ;
 H1      LD A,H
         ;SUB #C0
         ;JR NZ,OKHAUT
         ;LD A,L
         ;CP #50
         ;JR C,STOPUP
 ;
 OKHAUT  CALL ADSUP
         ;DJNZ H1
         ;LD (VISAD),HL
 ;
         ;LD HL,(COINBD)
         ;LD B,4
 H2      CALL ADSUP
         ;DJNZ H2
         ;LD (COINBD),HL
 ;
         ;LD BC,LSP1
         ;AND A
         ;SBC HL,BC
         ;CALL ADINF
         ;LD (ADPROV),HL
         ;SCF
         ;RET
 ;
 STOPUP  CALL CHDIR        ;On ne peut plus monter donc on essaye de changer
         ;LD A,(HL)         ;;de direction . On enleve un eventuel bit de
         ;AND %11111110     ;de direction vers le haut et si c'etait le seul
         ;JR Z,STOPUP       ;bit mis on recommence .
         ;JR NEWDIR
 ;
 ;- A DROITE -
 ;
 ADROIT  LD HL,(COINBD)
         ;CALL TSTLAT
         ;CP #4F
         ;JR Z,STOPDRO
 ;
         ;INC HL
         ;LD (COINBD),HL
 ;
         ;LD HL,(VISAD)
         ;LD (OLDADV),HL
         ;INC HL
         ;LD (VISAD),HL
         ;SCF
         ;RET
 ;
 STOPDRO CALL CHDIR        ;Meme principe que pour haut et bas
         ;LD A,(HL)
         ;AND %11110111
         ;JR Z,STOPDRO
         ;JP NEWDIR
 ;
 ;- A gauche -
 ;
 AGAUCH  LD HL,(VISAD)
         ;CALL TSTLAT
         ;OR A
         ;JR Z,STOPGAU
 ;
         ;DEC HL
         ;LD (VISAD),HL
         ;LD BC,LSP
         ;ADD HL,BC
         ;LD (OLDADV),HL
 ;
         ;LD HL,(COINBD)
         ;DEC HL
         ;LD (COINBD),HL
         ;SCF
         ;RET
 ;
 STOPGAU CALL CHDIR        ;Comme pour haut , bas
         ;LD A,(HL)
         ;AND %11111011
         ;JR Z,STOPGAU
         ;JP NEWDIR
 ;

     Suivent les routines qu'il n'est  pas  nécéssaire de montrer une nouvelle  fois .

La démonstration vous montrera  les  25  sprites rebondissant joyeusement sur les  bords de l'écran  et  se  croisant  sans  complexes  .  La méthode  d'affichage est suffisament rapide pour que ce croisement provoque à peine un  léger clignotement . Il peut arriver que 2 sprites superposés suivent la même  trajectoire . Dans ce cas c'est un peu confus .

Pour le chapitre suivant nous aborderons la rencontre entre 2 sprites .

SOS PROGRAMMEURS

★ ANNÉE: ???
★ AUTEUR: MICHEL MAIGROT

Page précédente : Graphic - 15 - Animation de Sprites (SOS Programmeurs)
★ AMSTRAD CPC ★ DOWNLOAD ★

Other platform tool:
» SOS7DEMODATE: 2011-06-03
DL: 427 fois
TYPE: ZIP
SIZE: 8Ko
NOTE: 40 Cyls
.HFE: NON

Je participe au site:
» Newfile(s) upload/Envoye de fichier(s)
★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding Src's » Graphic - Schneelandschaft (CPC Amstrad International)
» Coding Src's » Torus
» Coding Src's » Lamp
» Coding Src's » Départ en Vacances
» Coding » Graphic - 14 - Animation des Sprites (SOS Programmeurs)
» Coding Src's » 3D Shape Rotator

QUE DIT LA LOI FRANÇAISE:

L'alinéa 8 de l'article L122-5 du Code de la propriété intellectuelle explique que « Lorsque l'œuvre a été divulguée, l'auteur ne peut interdire la reproduction d'une œuvre et sa représentation effectuées à des fins de conservation ou destinées à préserver les conditions de sa consultation à des fins de recherche ou détudes privées par des particuliers, dans les locaux de l'établissement et sur des terminaux dédiés par des bibliothèques accessibles au public, par des musées ou par des services d'archives, sous réserve que ceux-ci ne recherchent aucun avantage économique ou commercial ». Pas de problème donc pour nous!

CPCrulez[Content Management System] v8.7-desktop/cache
Page créée en 098 millisecondes et consultée 1011 fois

L'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.