CODING ★ COURS DE GRAPHISME - CHAPITRE 6 : REAGIR AU TEST DE COLLISION SUR LES COULEURS ★

Graphic - 21 - Reagir Au Test de Collision sur les Couleurs (SOS Programmeurs)

Comment réagir lors d'une rencontre entre 2 sprites ? Une seule réponse : Comme on veut ! Mais  pas  n'importe  comment  ...  A  titre d'exemple , nous poursuivons le développement du même programme comme suit :

Le sprite numéro 6 (Petit  missile  vert  à  ailes delta rouges) détruira tout autre sprite lorsqu'il en touchera  un  lors  de son déplacement vers le haut . Une collision vers le bas  ou  latérale restera inoffensive . Facile à dire mais le faire c'est mieux ! Ce n'est pas aussi évident qu'on le croit.

Puis que seule la  collision  vers  le  haut  est  destructive , seule la sortie de cette routine sera modifiée  .  Il faudra différencier l'abandon du déplacement par rencontre avec une  couleur  de  la rencontre avec la bordure écran . Cette sortie spécifique établie ,  il  suffira de tester le numéro du sprite actif (Vous voyez qu'il à son utilité ...) , si ce n'est pas le 6 , on continuera comme par le passé , si c'est  6 , il faudra résoudre une série de problèmes :
 

1 : A ce stade on  sait  que  le  sprite  numéro 6 vient de rencontrer un octet écran qui contient autre chose que  la  couleur du fond ET C'EST TOUT .  Rien ne prouve en effet que  cette  couleur  tombée  du ciel appartienne à un sprite , cela pourrait éventuellement être un  élément  du décor . Il va donc faloir s'en assurer . Pour ceci ,  une routine (qui sera présentée plus loin)  devra :
A / Mémoriser l'adresse de collision .

B / Tester toutes les  positions  écran  mémorisées  dans la table ZONESP pour voir si l'adresse de collision  se  situe  sur l'emplacement de l'un des sprites .

C / Réagir en fonction du résultat obtenu .

2 : Si après ce test on  s'apperçoit  que le sprite 6 doit détruire celui qu'il vient de rencontrer il  faut  encore  enterrer le cadavre en l'effaçant (par exemple) et le  retirer  du  jeu  pour  ne  pas  le  réafficher après sa destruction  ce  qui  ferait  désordre  .   L'octet  STATSP  prend  toute  sa signification car mis à 0 au lieu de  #FF  , il informera le programme que ce sprite n'est plus en jeu .
Pour obtenir ce petit miracle  ,  on  commencera  par modifier la routine  ENHAUT comme suit :

 ;
 ENHAUT  LD HL,(VISAD) ;Ce qui differe est commente en majuscules .
  LD B,4
 TSH1 LD A,H
  ;SUB #C0
  JR NZ,OKHAUT
  LD A,L
  CP #50
  JR C,STOPUP
 ;
 OKHAUT  CALL ADSUP ;Monter avant le test couleurs ! Sinon on testerait
;        ;la ligne du sprite et le déplacement serait toujours
;        invalide !
 ;
;- Test couleur vers le haut VERSION 2 -
 ;
  LD D,H     ;Copier adresse en cours dans DE pour tester
  LD E,L     ;sans modifier HL
  LD C,LSP   ;Balayer la ligne sur la largeur du sprite
 TSTUP   LD A,(DE)
  OR A    ;Si contenu écran pas 0 , la ligne est occupee
  JR NZ,STOPCOL ;ON SAUTE AU TEST DU NUMERO DE SPRITE POUR VOIR
  INC DE     ;COMMENT REAGIR A LA COLLISION .
  DEC C
  JR NZ,TSTUP
  DJNZ TSH1
 ;
;- Deplacer vers le haut -
 ;
  LD (VISAD),HL
  LD HL,(COINBD)
  CALL ADSUP
  CALL ADSUP
  CALL ADSUP
  CALL ADSUP
  LD (COINBD),HL
 ;
  LD BC,LSP1
  AND A
  ;SBC HL,BC
  CALL ADINF
  LD (ADPROV),HL
  ;SCF
  RET
 ;
 STOPCOL LD A,(NUMSP)  ;ICI LA SEULE COLLISION QUI NOUS PREOCCUPE EST CELLE
  CP 6    ;DU SPRITE NUMERO 6 AVEC UN AUTRE QUELCONQUE .
  JR NZ,STOPUP  ;SI CE N'EST PAS LE 6 CE N'EST RIEN ON CONTINUE .
  LD (ADCOLLIS),DE ;ON MEMORISE L'ADRESSE DE COLLISION ET ON VA VOIR
  CALL COLIUP   ;SI L'UN DES 25 SPRITES EST TOUCHE . LE CARRY EST
  RET C      ;MIS SI OUI ET ON ARRETE TOUT .
 ;
 STOPUP  RES 0,(IY+0) ;SINON LA COULEUR RENCONTREE N'APPARTIENT PAS A UN
  XOR A     ;SPRITE ET ON CONSIDERE QUE C'EST UN OBSTACLE .
  RET    ;Déplacement impossible enlever le bit correspondant
;

Ceci est très simple  à  comprendre  mais  reste  a considérer la routine COLIUP qui est plus subtile il  faudra  en  effet  la rendre très rapide , de toute manière elle ralentira toujours le programme mais cela ne doit pas être décelable à l'œil nu ! Pour  mieux comprendre son fonctionnement regardez ce croquis .

     ;+---------+
  VISAD -->!   ***   !
    ;!  * * *  !
    ;! ******* !
    ;!   ***   !
    ;!  *****  !
    ;! ******* !<-- & COINBD du sprite rencontré mémorisés dans ZONESPT.
    ;+---------+
   ; ^
   ; +------------- Adresse ADCOLIS ou ça va cogner .
   ; +---------+
  VISAD ----->! * !<--- Le sprite numéro 6 qui monte vers un sprite
   ; ! * !  quelconque .
   ; ! * !
   ; !   ***   !
   ; !  *****  !
   ; ! ******* !<---- & COINBD du sprite actif en zone programme .
   ; +---------+

La collision sera enregistrée sur la  ligne  du bas du sprite rencontré .  On commencera donc le test depuis  COINBD  en  balayant  la ligne de droite à  gauche pour gagner un maximum  de  temps  .  Si  on  devait effectuer un test  similaire vers :
 
LE BAS : On balayerait de gauche à droite en commençant par VISAD .
LA GAUCHE : De bas en haut en commençant par COINBD .
LA DROITE : De haut en bas en commençant par VISAD .

Soit 1 routine différente par direction envisagée .

Voyons aussi le cas ci-dessous .

     ;+---------+
    ;!   ***   !
    ;!  * * *  !
    ;! ******* !<--- La collision sera enregistrée ici si le sprite
    ;!   ***   !      ; tamponneur monte en diagonale vers
    ;!  *****  ! +---------+  la gauche .
    ;! ******* ! ! * !
    ;+---------+ ! * !
        ; ! * !
        ; !   ***   !
        ; !  *****  !
        ; ! ******* !
        ; +---------+

  Il est visible qu'en diagonale la  collision  peut ne pas se produire sur la ligne la plus  basse  mais  au  milieu  ou  tout  en  haut  . Si l'on veut augmenter l'efficacité du missile , il suffira  de tester plus d'une ligne en remontant le test d'un cran vers le  haut  si  la 1ère ligne ne valide pas la collision . Cela rallonge le temps  d'exécution mais il faut aussi envisager
 les cas suivants :
 

     ;+---------+
    ;!   ;!  Pour une raison connue du seul créateur de la table de
    ;!   ***   !  sprites , celui-ci présente une ligne vide ici --+
    ;! *** *** !                           ;!
    ;! *** *** !                           ;!
 +----> !   ***   !                           ;!
 !   !   ;! <-------------------------------------------------+
 !   +---------+
 +------------------------- La ligne de collision enregistrée  par  ENHAUT
    ;+---------+   ;ne sera pas la plus basse du sprite mais celle
    ;! * !   ;ou se trouvent les 1ères couleurs qui  est  au
    ;! * !   ;dessus de COINBD , il faudra donc tester 2
    ;! * !   ;lignes si l'on veut valider la collision .
    ;!   ***   !
    ;!  *****  !
    ;! ******* !
    ;+---------+

Même problème ci-dessous , la zone  testée  est celle au dessus du sprite en cours et la couleur déterminant  la  collision  ne se rencontre que sur la 3ème ligne .
 

     ;+---------+
    ;!   ;!
    ;!   ***   !
    ;! *** *** !
    ;! *** *** !. . . . <-- ADCOLLI est trouvée sur cette ligne .
    ;!   ***.  !   .
    ;!   ***.  !   .
    ;+------.--+   .
      ; .   ;.
      ; +---------+
      ; ! * !
      ; ! * !
      ; ! * !
      ; !   ***   !
      ; !  *****  !
      ; ! ******* !
      ; +---------+

Donc dans le cas ou un sprite  est  entouré  d'une ligne vide , ne tester qu'une ligne équivaut à le rendre indestructible  ! Dans celui ou la ligne de collision laisse des vides , il  sera  d'autant  plus difficile de le toucher que le nombre de lignes testées sera faible .

On pourrait résoudre ces  inconvénients  en  supprimant  le  test sur les couleurs et en balayant la table des  sprites  à chaque test histoire de voir si un sprite bloque la route mais dans ce cas :

1 / La vitesse d'exécution du programme serait divisée par 2 .

2 / Si une couleur  n'appartient  pas  à  un  sprite elle sera ignorée et effacée par le passage du sprite .

Alors restons en là et voyons  la  routine  COLIUP  ou l'on notera que le test de comparaison se fait en 2 fois , Comparaison sur l'octet fort puis sur l'octet  faible  .   En   effet   ,   PUSHHL-ANDA-SBCHL,DE-POP  HL- JRZ,TOUCHE est beaucoup trop long à exécuter ! Et on ne peut vraiment tester  sur 8 bits seulement car certains groupes  de 8 lignes écran (Comme le groupe  4 , voyez  SCRENMAP  de  SOS5)  commençant  par  #C0F0  voit  2  octets forts  différents sur une meême ligne (De #C0FF  on  passe  à #C100) et en ces points  particuliers de l'écran , le test aurait du mal à s'effectuer !
 
 

;
;- Tester avec quel sprite on entre en collision (Par dessous) -
 ;
 COLIUP  LD B,NBTOANI  ;Nombre a animer donc a tester
  LD IX,ZONESPT ;Debut de la table des sprites
  LD DE,(ADCOLLIS) ;Adresse de collision detectee par ENHAUT
 ;
 BCLCOLLIS PUSH BC   ;On preserve le nombre a tester
  LD A,(IX+7) ;Voir statut sprite
  INC A    ;Si <> de #FF , il est deja hors jeu , on abandonne
  JR NZ,NOTEST ;le test de celui-ci pour passer au suivant .
 ;
  LD B,2   ;Hauteur a tester 2 lignes sont raisonnables .
  LD C,LSP    ;Largeur d'un sprite
  LD L,(IX+4) ;Adresse de COINBD prise dans la table des sprites.
  LD H,(IX+5)
 ;
 BCLC2   PUSH HL     ;Preserver COINBD en cours de test
  PUSH BC     ;et les hauteurs et largeurs de la zone a tester
 ;
 BCLC1   LD A,H   ;Tester octet par octet gagne du temps
  CP D     ;On commence par l'octet fort des adresses
  JR NZ,PATOUCH
  LD A,L   ;Et on ne teste le faible que si la comparaison
  CP E     ;precedente est valide
  JR Z,TOUCHE ;Si les 2 adresses coincident le sprite teste
;        ;est touche par le sprite numéro 6 .
 PATOUCH DEC HL   ;Sinon on continue a tester la ligne en cours
  DEC C
  JR NZ,BCLC1
 ;
  POP BC   ;Et si la collision n'est pas verifiee sur cette
  POP HL   ;ligne on va voir sur la ligne au dessus .
  CALL ADSUP
  DJNZ BCLC2
 ;
 NOTEST  LD BC,11    ;Un sprite vient d'etre teste , on passe au suivant
  ADD IX,BC   ;en avancant de 11 octets dans la table .
  POP BC
  DJNZ BCLCOLLIS
  XOR A    ;Ici on constate qu'aucun sprite n'est touche , on
  RET      ;enleve le CARRY et c'est fini
 ;
 TOUCHE  POP BC   ;Un sprite est touche , on remet la pile en etat
  POP HL
  POP BC
  LD (IX+7),0 ;On signale sa destruction en modifiant l'octet
  CALL EFFSP  ;qui correspond a STATSP , on l'efface
  ;SCF      ;et on met le CARRY pour signaler sa disparition
  RET      ;lors du retour en HAUTSP . Si l'on ne met pas le
;        ;CARRY , le sprite sera quand me^me détruit mais le
;        ;missile N.6 changera de direction à chaque choc .
 ;
;- Efface le sprite touche -
 ;
 EFFSP   LD BC,HSP  ;Ici IX pointe toujours sur le sprite détruit , on
  LD H,(IX+3) ;extrait donc VISAD de la table pour l'effacer et
  LD L,(IX+2) ;de cette maniere , les parametres du sprite en cours
;       ;restent inchanges au cours de toutes les operations
 BCLEFF1 PUSH HL    ;de test et d'effacement .
  PUSH BC
  LD B,C
 BCLEFF2 LD (HL),0
  INC HL
  DJNZ BCLEFF2
  POP BC
  POP HL
 ;
  LD A,H
  ADD A,8
  LD H,A
  JR NC,EXIEFF
  LD DE,#C050
  ADD HL,DE
 EXIEFF  DJNZ BCLEFF1
  RET
;

C'est tout ce qu'il faut pour supprimer un sprite suite à une collision ,  il ne reste  plus  qu'une  petite  modification  à  effectuer  dans la boucle  principale pour ignorer les cadavres .
 

 ;
;- Boucle pour deplacer un sprite -
 ;
 NXTANIM CALL TRANSP
  LD A,(STATSP) ;VERIFIER QUE LE SPRITE N'EST PAS HORS JEU , SI C'EST
  OR A    ;LE CAS ON SAUTE TOUTE LA BOUCLE .
  JR Z,ESTMORT
 ;
  PUSH BC
  CALL TSTMOVE
  CALL AFFISP
  CALL SPTRANS
  POP BC
 ;
 ESTMORT DJNZ NXTANIM
  JP RECOM
;

La démonstration mettra en évidence un  problème majeur , plus on détruit de sprites , plus le  programme  accélére  !  On  aurait du mettre une petite temporisation pour compenser l'annulation  de  chaque  sprite ... Nous allons faire encore mieux dans le prochain chapitre .

SOS PROGRAMMEURS

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

Page précédente : Graphic - 20 - un Nouveau Test de Collisions sur les Couleurs
★ 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 » Graphic - CPC 29 - Création et Animation de Sprites (CPC Revue)
» Coding Src's » Detect CRTC type by Rhino
» Coding Src's » Ellipse (CPC Amstrad International)
» Coding Src's » Graphik (CPC Amstrad International)
» Coding Src's » Técnicas de dibujo en tres dimensiones (Amstrad Especial)
» Coding Src's » Quasar Test CRTC v2.0 (OffseT)
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
Page créée en 157 millisecondes et consultée 2173 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.