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 œuvre 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 déplacement
 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    ;Après 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  après TRANSP , le
;pointeur POINTSP pointe donc la zone suivante  . Pour remettre les donnees a
;la même 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 déplacement 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-être 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'était 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
★ AMSTRAD CPC ★ DOWNLOAD ★

Other platform tool:
» SOS7DEMODATE: 2011-06-03
DL: 1769
TYPE: ZIP
SiZE: 8Ko
NOTE: 40 Cyls
.HFE: Χ

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding Src's » OCP .WIN load
» Coding Src's » Graffitis (Amstrad Magazine 15)
» Coding » Graphic - 09 - Creation Animations Graphiques - Animation Pixels et Case Par Case (SOS Programmeurs)
» Coding Src's » Puddle (Computing with the Amstrad)
» Coding Src's » Test CRTC v1.0 (MADRAM , amslive n16)
» Coding Src's » Créons des volumes
Je participe au site:
» Vous avez des infos personnel, des fichiers que nous ne possédons pas concernent ce programme ?
» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.732-desktop/c
Page créée en 477 millisecondes et consultée 2656 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.