CODING ★ ANIMATION ET GESTION DE SPRITES: DEPLACEMENT MULTI-SPRITES, TEST DE COLLISION ★

Graphic - CPC 33 - Animation et Gestion de Sprites - Deplacement Multi - Sprites - Test de Collision (CPC Revue)

C'est reparti. Après avoir étudié différentes manières de déplacer un seul sprite, nous devons maintenant réussir à en animer plusieurs, les faire se rencontrer et réagir à ces rencontres. Ceci va nous entraîner sur la pente savonneuse de la complexité ! Tant qu'à faire, autant glisser jusqu'en bas en créant un jeu d'arcade complet dont l'utilisateur pourra à loisir modifier l'ensemble des paramètres.

J'ai évoqué, dans une série précédente, les avantages (notamment en simplicité et rapidité de traitement), d'une table de sprites de tailles identiques. Ce programme, utilisant ce type de table, voici d'abord un petit utilitaire nommé "SGTFIXE", qui convertit une table TRAVAIL NON RELOGEE en table à intervalles fixes. Pour créer cette table de travail, vous devrez pour chaque sprite, entrer les mêmes hauteur et longueur de grille, et sauvegarder avec l'option grille complète, même si votre dessin ne remplit pas la grille. Mode d'emploi : lancer le programme, charger la table à modifier et appuyer sur le bouton. Si un sprite de dimension différente des autres est rencontré, un message d'erreur est affiché. Sinon, les octets inutiles et la table des adresses sont éliminés et le programme affiche les nouvelles données avant de sauvegarder la nouvelle table avec le surfixe "TSF". Cette table ne comportant aucun adressage, elle peut être rechargée à n'importe quel point de la mémoire. (40000 pour notre jeu). Par contre, il ne faudra pas oublier de préciser l'adresse de chargement voulue (LOAD"TABLE.TSF",Adresse), sinon surprise. Pour l'instant, évitez-vous du souci en utilisant la table "TF1CPCMO.TSF" donnée sous forme de DATAS.

BLOODY INVADERS : FONCTIONNEMENT DU PROGRAMME

Le programme est conçu pour fonctionner en mode 0, il peut toutefois fonctionner en mode I, moyennant quelques retouches. (Voir section modifications possibles).

TABLES DE GESTION POUR TABLE DE SPRITES

Il est question d'animer un nombre X de sprites. Pour cela, le programme aura besoin de conserver en mémoire :

  • La position d'affichage de chaque sprite (en adresse écran).
  • Le coin opposé à l'adresse d'affichage (pour les tests de collision).
  • La direction où doit aller le sprite. Il y a donc obligation de créer une zone de données spécifique à l'animation. Nous pouvons compléter cette zone par :
  • L'adresse des octets composant le dessin dans la table de sprites. Cela nous évitera de manipuler plusieurs pointeurs et de recalculer cette adresse à chaque affichage.
  • La hauteur et la longueur du sprite. Pas vraiment nécessaires quand on utilise une table fixe, mais indispensables avec une table variable.
  • L'état du sprite. Inutilisé par BLOODY INVADERS mais très utile pour des applications particulières. Les données concernant l'adresse de visualisation et la position du motif dans la table de sprites pourraient être données directement sous forme de DEFW. Comme j'ai voulu faciliter au maximum l'entrée de modifications à partir du BASIC, une table contenant les données des sprites à utiliser sera utilisée pour initialiser la table de gestion. Regardez attentivement la figure 1, elle résume le principe de passages des paramètres dans la section initialisation. Voyez aussi le chapitre signification des variables pour plus de détails. Le programme utilise un générateur de directions aléatoires DIRHAS. Ce dernier est basé sur l'état du registre R (REFRESH) qui varie en permanence et dont le contenu est relativement imprévisible. DIRHAS donne une direction de 1 à 8 (dans le sens des aiguilles d'une montre, 1 étant la verticale).

La table ae gestion se compose d'autant de blocs de 10 octets qu'il y a de sprites à animer. Le programme doit exploiter chaque bloc un par un pour gérer l'animation de chacune des images. Plutôt que de monopoliser un registre IX ou IY, pour garder en permanence une trace de l'adresse du bloc concerné (ceci afin de pouvoir transmettre les paramètres résultant des opérations en cours), le bloc complet est copié dans une zone de 10 octets (SPTA-DRES), avec labels, qui permet un passage plus direct des paramètres. A la fin des opérations sur le sprite en cours, la zone SPTADRES est recopiée à l'emplacement d'origine préservé dans ADSPTAFF (TABL-PROG & PROGTABL).

ROUTINE DE DEPLACEMENT

Elle est similaire à celle décrite dans les articles précédents à une exception (de taille) près. Elle sera sollicitée par plusieurs routines différentes, (les envahisseurs, le test joystick, les missiles). Trois routines différentes, donc plusieurs points de retour différents. De plus les coordonnées de directions de 1 à 8 ne peuvent s'appliquer directement au test du joystick.

La première chose à faire est de convertir le résultat du test ioystick (BIT 0, 1, 2, 3 selon direction) en un nombre de 1 à 8 qui sera conforme au système de direction choisi pour les envahisseurs. La même routine de déplacement pourra alors être utilisée pour tous les sprites.

Reste le problème des points de retour. Pour ceux-ci, nous utiliserons les instructions JP (HL) et JP (IX). (LD HL,30000 - JP (HL) aura pour effet JP 30000). Les routines SAUTDIR (joystick) et SAUTDIR2 (autres), calculent l'adresse de la (plusieurs en cas de diagonale) routine de direction à appeler (par incrémentation du pointeur TABLEDIR).

Au retour, HL contient l'adresse de la routine sélectionnée. Chacune de ces routines se termine par un J P (IX).
Il suffit donc de donner l'adresse de retour dans IX avant de faire un JP (HL).

Ce procédé permet de modifier encore le point de retour en cours d'exécution, il suffit de modifier la valeur de IX pour changer l'adresse de retour.

LA ROUTINE D'AFFICHAGE

Àvec la routine d'affichage et déplacement sur 3 plans, j'ai mentionné qu'un charcutage de ce programme conduisait à une routine d'animation sur fond monochrome (PAPER 0), incomparablement plus rapide. Elle est employée dans ce programme. Le déplacement pixel par pixel rendrait le programme plus complexe et plus lent. L'est un mode case par case qui a été choisi.

VITESSE RELATIVE DES DIFFERENTS SPRITES

Il est intéressant de pouvoir régler séparément la vitesse de chaque groupe de sprites. On pourrait être tenté d'utiliser STEP X-Y pour ceci. Cela fonctionnerait très bien à une exception près : l'œil ne verrait pas la différence mais le programme si I Supposons que STEP envahisseurs soit différent de STEP sprite joystick, dans la plupart des positions, il n'y aura pas concordance entre les 2. oi un missile est tiré à ce moment, sa trajectoire sera prise entre deux positions STEP envahisseurs. La rencontre ne sera pas reconnue par le programme et une vive irritation du programmeur s'en suivra. Il est bien plus efficace d'inclure la boucle de déplacement des sprites à l'intérieur d'une autre, qui se répétera tant que le paramètre vitesse sera différent de 0.

Un usage possible du paramètre état sprite serait de contenir une donnée indiquant une vitesse de déplacement spécifique pour chaque sprite. Voir aussi variables.

TEMPORISATIONS

Les opérations de calcul et d'affichage prennent du temps. Aussi, si le programme commence avec 20 envahisseurs et que le but du jeu est de les abattre, un envahisseur détruit n'est plus affiché. Le programme a moins de travail à accomplir et accélère progressivement. Cet effet est mis à profit dans "SPACE INVA-DER". J'ai jugé utile de l'annuler. Pour cela, au îieu de sauter directement à la suite des opérations lorsqu'un envahisseur est reconnu comme détruit, le programme est détourné vers une boucle de temporisation.

Pour le sprite joystick, c'est pareil. S'il ne se déplace pas, le programme s'accélère. Donc qu'il y ait eu déplacement ou non, on effectue quand même l'opération d'affichage pour équilibrer le programme.

Pour les missiles, je n'ai effectué aucune compensation pour mettre en évidence ce problème. Le remède est simple : en EXITJOY, remplacer le test et saut conditionnel par un saut absolu JP MISSILE ; dans la routine MISSILE, après NEXTMIS, changer JR Z, MISSUIVA en JR Z, nom de votre routine de temporisation et terminer cette routine par JR MISSUIVA. Qu'il y ait ou non un missile de tiré, la routine missile sera sollicitée et si votre temporisation est correcte, le programme tournera toujours à vitesse constante.

TESTS DE RENCONTRE ET
DE COLLISION

Les exemples d'animation précédents incluent un test sur les lignes et colonnes écran, interdisant aux sprites de sortir de l'écran. Bien que très primaire, cette routine n'en constitue pas moins un test de collision du type : rencontre obstacle, donc stop tant qu'une nouvelle direction valide n'est pas fournie au programme. Avant d'aller plus loin, il devient nécessaire d'expliquer le principe de fonctionnement du jeu :

— Un nombre NBSPMAX d'envahisseurs apparaît sur l'écran en un point prédéfini, puis c'est le tour du sprite joystick.
— Les envahisseurs se déplacent d'une position, dans une direction donnée par DIRHAS, chacun leur tour. Tant que VAUTO est < > 0, cette boucle se répète.
A ce stade, il faut déjà étudier 2 cas :
Un envahisseur veut sortir de l'écran.
2 envahisseurs se rencontrent.
— Le sprite ioystick se déplace (si vous le désirez). Donc 2 possibilités de plus :
— Le sprite joystick veut quitter le champ de bataille (hors écran).
— Le sprite joystick touche un envahisseur.
— Pour sa défense, le sprite joystick dipose de missiles. Donc :
— Le missile se perd hors de l'écran.
— Le missile touche un envahisseur. Vice suprême, de temps à autre les envahisseurs posent une mine (qui ne se déplace pas).
Un envahisseur touche une mine.
Le vaisseau (sprite joystick) touche une mine.
Un missile touche une mine.
— La moindre des choses est qu'un envahisseur touché par un missile, prenne la peine d'exploser pour saluer votre exploit. D'ou k-l-m = g-h-i en substituant le mot explosion au mot mine.

Soit 13 possibilités de collisions auxquelles viennent s'ajouter ce que l'on pourrait appeler les "collisions secondaires". Considérons un missile (A) et un envahisseur (B). L'ordinateur déplace ces sprites à tour de rôle. Pour nous l'essentiel est que la rençontre entre les deux ait lieu. Pour le programme, il est vital de savoir si c'est (A) aui rencontre (B) au cours de son déplacement ou bien l'inverse. (D'autant plus que les dimensions du missile sont différentes des dimensions des envahisseurs).

Etablissons d'abord le tableau de toutes les possibilités :

    ; A   ;B   ;C  D  E   F
   ; INVADER VAISSEAU MISSILE MINE EXPLOSION HORD-ECRAN
--------------------------------------------------------------------
1 INVADER  x   ;x   ;x  x  x   x
2 VAISSEAU x   ;0   ;+  x  x   x
3 MISSILE  x   ;x   ;+  x  x   x
--------------------------------------------------------------------

Les obstacles fixes ne pouvant qu'être rencontrés, ne sont représentés qu'une seule fois. Les collisions impossibles sont représentées par un 0. La possibilité de modifier la vitesse relative des sprites rend certaines collisions possibles avec VJOY > VMISS. Elles sont notées par un "+".

Le programme doit réagir de la manière suivante à ces rencontres :

1A, 1D, 1E, 1F: L'envahisseur change de cap.
1B : Vous êtes détruit.
1C : L'envahisseur est détruit.
2A, 2C, 2D, 2E : Vous êtes détruit.
2F : Vous ne pouvez aller dans cette direction.
3A : L'envahisseur est détruit.
3B : Vous êtes détruit.
3C : Ils s'ignorent (pas de test).
3D : Le missile détruit une partie de la mine.
3E, 3F : Le missile est perdu. Maintenant, prenons les choses dans l'ordre.

REACTIONS AUX SORTIES
D'ECRAN

Gros avantage d'avoir une seule routine de déplacement pour la totalité des sprites : on peut y inclure la totalité des tests et déterminer la validité d'un mouvement par l'état du CARRY. Si un déplacement est possible, SCF met le carry sinon XOR A ou AND A l'annule.

Donc, au retour des tests, la routine appelante peut tester le CARRY et réagir en conséquence.

Pour les sorties d'écran, dans la routine AUTOMOVE le CALL NC, DIRHAS (exécuter routine si bit CARRY = 0), change la direction de l'envahisseur.

Si cette nouvelle direction est invalide, elle sera remodifiée au prochain tour de boucle. Il arrive aonc parfois qu'un envahisseur "piétine" un peu si une suite de directions impossibles lui est donnée.
Pour les raisons évoquées dans la section "TEMPORISATIONS", le sprite joystick est affiché quoiqu'il arrive. Pour cette raison, les routines de déplacement réinitialisent la position d'origine en cas de mouvement hors écran. Donc pas besoin de tester le carry dans JOY 0.
Pour les missiles, le JR NC, RESET-MIS en EXITMISS supprime le missile. Comme on peut le voir, la réaction aux sorties d'écran est somme toute assez simple.

CPC n° 33

★ EDITEUR: CPC Revue
★ ANNÉE: ???
★ AUTEUR: MICHEL MAIGROT
 

Page précédente : Graphic - CPC 29 - Création et Animation de Sprites

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

Lien(s):
» Coding Src's » Screen Compact
» Coding Src's » Graphic - Amstrad Character Modes (Popular Computing Weekly)
» Coding Src's » Quasar Test CRTC v2.0 (OffseT)
» Coding Src's » Ah, Les vacances : Le Hamac
» Coding Src's » ARTIFICE (CPC Infos)
» Coding Src's » Rotating Sphere
Je participe au site:

» 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.7-desktop/c
Page créée en 278 millisecondes et consultée 2803 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.