CODING ★ ANIMATION ET GESTION DE SPRITES ★

Graphic - CPC 34 - Animation et Gestion de Sprites (CPC Revue)
Pour des raisons de place, il ne nous est pas possible de publier le listing assembleur commenté correspondant à l'article.
Les personnes qui voudraient tout de même obtenir ce listing le trouveront sur la disquette CPC 17 ou sur la cassette 34.

REACTIONS AUX RENCONTRES AVEC UN AUTRE SPRITE

Là, c'est plus dur, accrochez-vous aux sprites, j'enlève les octets ! Pensez aussi à regarder la figure 2.

Test sur les couleurs.

Encore une fois, je ferai référence à l'exemple d'animation sur 3 plans différents. Ce dernier teste la valeur d'un pixel afin de déterminer s'il doit sortir sur l'écran. Nous pouvons donc imaginer un test basé sur le contenu de l'écran à la position QUI VA ETRE OCCUPEE par le sprite en cours de déplacement. Ce sera d'autant plus aisé que le programme présent ne considère qu'un fond uni. Donc toute position sur un octet écran contenant 0 est valide, sinon il y a déjà quelqu'un sur la place. Un détail saute aux yeux : il est ainsi possible de savoir si la place est libre ou occupée, mais impossible de déterminer si l'emplacement est occupé par un porte-avions ou un poisson rouge. On pourrait y remédier en fixant une couleur spécifique à certains sprites (par exemple, entourer le sprite joystick de blanc et ne jamais entourer les envahisseurs de blanc), et tester les valeurs des pixels pour savoir de qui il s'agit. Cela marche, mais on se trouve rapidement limité en couleurs. Cette solution simpliste n'a été retenue que pour reconnaître les mines (INA-CEXPL dans TESTMISS).

Test sur les adresses.

C'est plus compliqué et justifie pleinement l'emploi d une table de gestion. En effet, cette dernière contient en permanence les positions respectives et l'encombrement de chaque sprite. Donc, il suffit de prendre la future adresse de visualisation du sprite, et en commençant par le premier bloc de la table de gestion chercher si ce point se trouve à l'intérieur du rectangle dont les coordonnées sont contenues dans un des blocs gestion.

Si le dessin se déplace vers le haut ou à gauche, il est plus rapide de tester VISADRES du sprite en mouvement par rapport à COINOPPO contenu dans le bloc. S'il se déplace vers le bas ou à droite, ce sera exactement l'inverse. Tant qu'aucune collision n'est détectée, un compteur est incrémenté. Ceci permet donc de connaître le numéro de sprite rencontré. (Pour des cas particuliers, un numéro spécifique pourrait être placé dans la case ETATSPT). En cas de test réussi, aller chercher ce numéro dans le bloc de gestion où s'est arrêtée la recherche et agir en conséquence.

C'est mieux, mais ne vous faites pas d'illusions, c'est plein de défauts.

  • Prend du temps et doit être exécuté à chaque déplacement, donc un coup dur pour la vitesse d'exécution générale.
  • Ce aui condamne à mes yeux ce type de test : il ne considère qu'un rectangle. Donc, si l'un des deux sprites ne remplit pas entièrement cette zone, la collision est enregistrée alors qu'il y a encore un espace physique entre les 2. Bonjour la précision...
  • Le test utilisé par BLOODY INVADERS : Il semble qu'une loi fondamentale de l'informatiaue postule : si deux méthodes différentes ne sont qu'à peu près satisfaisantes, combinez les deux pour résoudre le problème, feIle se vérifie ici : il suffit a'abord de balayer une ligne (ou colonne) à l'endroit qui va être occupé par le motif (BCLTSTCB-BCLTSTCH-BCLTSTCG & BCLTSTCD) dans les routines déplacement. Si la place est libre, rien ne se passe ; sinon, l'adresse écran où le test se révèle positif est préservée dans POSCOL et le programme est dérivé vers la routine QUELSPT qui effectue le test décrit en 2. Pour ne pas rendre cette routine illisible, le test ne tient pas compte du sens de déplacement et ne considère que POSCOL par rapport à VISADRES des sprites de la table. Notez qu'il faut toujours tester les lignes avant les colonnes, c'est beaucoup plus rapide.

Notes

Pour des raisons esthétiques, la plupart des sprites ont un nombre de pixels impair. Le test décrit ci-dessus ne considérant que la case mémoire écran complète, il laissera parfois un vide lors dès déplacements latéraux. (C'est fort peu visible). D'autre part, si le dessin ne remplit pas entièrement le rectangle, le test présentera le même défaut que s'il se faisait uniquement sur les adresses écran. Dans ce cas, il sera nécessaire d'améliorer le test sur les couleurs de manière à vérifier 2 octets.
Tester l'octet aui va se déplacer. S'il est à 0, le déplacement est possible, sinon tester l'octet qui va recevoir celui à déplacer. Si ce dernier est à 0, le mouvement est toujours possible. Si les deux contiennent une couleur, une collision va se produire.

Autre solution plus complexe : effectuer le calcul ae COINOPPO, non par rapport à la taille totale du rectangle mais par rapport au nombre de lignes et colonnes contenant des couleurs. Dans ce dernier cas, lors de la création des images avec sur-gene, les colonnes vides devront être celles de droite, les lignes vides, les lignes basses.

Dans le schéma test sur les adresses écran, on constate que lorsque la recherche en colonne à subi un é-chec, au lieu de quitter, elle retourne sur la recherche des lignes. C'est normal, seul l'octet fort est testé à la première recherche. Or, on retrouve dans la mémoire écran 4 lignes différentes (par exemple C000-C050-C0A0-C0F0) séparées par un intervalle de 8 lignes ayant le même octet fort (MSB). Si votre sprite occupe plus de 8 lignes de haut, et que sa position (VISADRES) est (toujours par exemple) #C00B, une collision en # C05B (sur sa 9e ligne) ne pourrait être prise en compte sans ce branchement. POSTEST est donc nécessaire pour garder la trace de l'endroit ou une équivalence MSB est trouvée, afin de pouvoir éventuellement reprendre la recherche à ce point.

Il aurait été plus évident de balayer la totalité du sprite à tester de gauche à droite et de haut en bas et en comparant l'adresse position complète avec POSCOL mais quelle lenteur ! Et surtout quel manque de style. Par contre, il serait plus élégant et plus rapide d'ajouter directement 80 à POSTEST pour avoir tout de suite l'adresse suivante correcte, et de limiter le nombre de nouvelles tentatives à effectuer en fonction de la hauteur du sprite. Je viens juste d'en prendre conscience. No-body's perfect I

Dernier détail.

Il est intéressant de pouvoir distinguer à quel groupe (envahisseurs, joystick, missile) appartient le sprite qui vient d'en rencontrer un autre. Le contenu de la variable SPTAFFICH est utilisé en entrée de QUELSPT, pour déterminer quelle routine spécifique il faut appeler. (Voir variables).


FIGURE 2

LA BONNE REACTION AU BON MOMENT

  • Remplacement d'un envahisseur cela ne peut se produire que lors d'une rencontre avec un missile.
  • L'envahisseur rencontre un missile (SUPPRIME) : dans ce cas, c'est simple car le programme contient en SPTADRES tous les paramètres de l'envahisseur. Normalement STOCKDIR ne contient qu'une valeur de 1 à 8 : mettons-y 128 et cela suffira pour signaler au programme que l'envahisseur concerné a eu un problème. Modifions IX pour ne pas revenir sur CALL NC, DIRHAS (ce qui annulerait l'opération effectuée). SPTADRES contient l'adresse aes octets composant le sprite envahisseurs, donnons-lui l'adresse des octets composant l'explosion. Au retour, le bloc SPTADRES modifié est recopié dans le bloc de aestion et la routine MOVEAUTO affichera une explosion à la dernière position enregistrée pour ce sprite.
  • Le missile rencontre un envahisseur (SUPPRIME 1) : le principe est le même mais la routine un peu plus compliquée car SPTADRES contient les paramètres du missile et il faut aller chercher ceux de l'envahisseur dans la table gestion.
  • Dans les 2 cas, SUPPRIM2 s'occupe d'ôter un envahisseur (NBSPACTI) et ajoute un point au score.
  • Mais pourquoi le missile n'est-il pas supprimé par ces routines ? Voilà une question, qu'elle est bonne I C'est simple : une explosion sera affichée avant que le missile ne soit à nouveau sollicité. Comme la rencontre d'un missile et d'une explosion supprime le missile à quoi bon se fatiguer...

Gestion d'une explosion.

Pour être un tant soit peu réaliste, une explosion doit grandir et se résorber. Donc 3 sprites de 3 tailles différentes. STOCKDIR contient au départ 128. A chaque tour de boucle MOVEAUTO, il est décrémenté. Chaque fois qu'il atteint une valeur critique, l'adresse du groupe d'octets à sortir à l'écran est changée.

Nous avons donc affichage successif d'une série de sprites donnant l'illusion d'une animation. A la fin de la série, STOCKDIR est mis à 0 pour que la boucle MOVEAUTO reconnaisse le sprite comme détruit. Ordre pour 5 opérations : SPEX1, SPEX2, SPEX3, SPEX2, SPEX1.

La suppression d'un missile est basée sur le même principe que celle d'un envahisseur.

La destruction de la totalité des envahisseurs marque la fin de la partie. Pour faire plus joli, la variable NBEXPLOS oblige le prog ramme à terminer le cycle des explosions en cours avant le retour au BASIC. Ce n'est pas le cas lorsque vous êtes détruit.

Avant de supprimer un missile ou un envahisseur, il doit être réaffiché une dernière fois. En effet, le test de collision ne considère pas le point où la collision se produit mais celui où la collision VA SE PRODUIRE ! Ce dernier déplacement comble un éventuel vide résiduel (voir tests collision). C'est donc plus agréable à l'œil.

D'autre part, il faut tenir compte qu'en cas de collision à mi-chemin entre 2 points STEP, les adresses de visualisation sont quand même modifiées, pour permettre un déplacement à la limite du possible. Donc ne pas réafficher préalablement et le sprite ne serait pas entièrement recouvert par l'explosion. C'est le cas du sprite joystick où cette correction n'est pas effectuée. La routine EFFACE et son appel sont donc inutiles. J'ai oublié de les supprimer avant d'imprimer le listing et de créer le code DATA. (Utilisateurs assembleur, attention, les omettre modifierait la position du contrôle).

RESURRECTION DES MORTS !

Pour justifier pleinement son nom, le programme remet en jeu (selon une temporisation aléatoire), les envahisseurs que vous avez eu tant de mal à détruire. Les blocs de gestion de ceux-ci étant complètement modifiés par l'explosion, ils doivent être réinitialisés dans les routines NEWINVAD et RESURECT.

DIRECTION DES MISSILES

Le programme connaît 3 modes de tir différents :

  • Le missile est toujours tiré vers le haut.
  • La direction du missile est celle donnée par le test joystick. Si ce test = 0, (pas de déplacement), le missile est tiré vers le haut.
  • Comme précédemment, mais si vous ne bougez pas, le missile part dans la dernière direction enregistrée par le joystick.

LES VARIABLES DE BLOODY INVADERS

Seules les variables ayant une importance stratégique sont données dans ce chapitre. Les valeurs des adresses sont écrites dans le listing assembleur et permettront aux utilisateurs de DATAS de modifier le contenu de ces dernières avec des POKES judicieux.

    • TABLESP : c'est le début des données concernant les envahisseurs. Le premier octet correspond au numéro du sprite à sélectionner dans la table des sprites, les deux suivants à l'adresse écran où il s'affiche pour la 1 re fois. Vous pouvez modifier à loisir cette table dans les limites suivantes :
    • Le numéro du sprite à afficher doit exister dans la table de sprites (Ni 0 ni > NBSPT).

    — L'adresse qui suit doit être une coordonnée écran et être calculée de manière que le sprite ne déborde pas de l'écran.
  • Le nombre de blocs donnés (3 octets) doit être égal ou supérieur au nombre maximum (NBSPMAX), d'envahisseurs à animer.

NOTE. Pour plus de lisibilité, les adresses écran sont "en clair", la routine BCLPARA en tient compte. N'oubliez pas que normalement le Z 80 range l'octet faible (LSB) en premier et que dans son langage, j'aurais dû écrire DEBF #01,#C0 pour l'adresse écran #C001.

  • TABLEJOY : même chose que TABLESP mais ne concerne que le sprite joystick, donc toujours 1 seul bloc de 3 octets.
  • TABLEXP : table des sprites explosions. Comme ces dernières doivent apparaître là où un sprite est détruit, il est inutile de déterminer une adresse écran préalable. Seul le numéro de sprite correspondant au dessin doit être donné. Le programme utilise 3 dessins pour animer une explosion. Si vous désirez modifier ce nombre, vous devrez modifier en conséquence la routine EXPLOSE.
  • NUMEXPLO : contient les numéros de sprites explosion à transférer dans TABLEXP. TABLEXP pourrait être paramétrée directement dans la version actuelle de ce programme. N'est utile que si vous voulez y apporter des modifications importantes. (Par exemple, utiliser une table de sprites avec des envahisseurs de tailles différentes et donc des dimensions d'explosion variables. Il vous faudra alors plusieurs tables NUMEXPLO1. 2... qu'une instruction LDIR mettra en place au bon moment dans TABLEXP).
  • NBEXPLO : nombre de sprites explosions à afficher successivement. Initialisé à 3. Toute modification doit se répercuter sur NUMEXPLO & EXPLOSE.
  • FLAGEXPLOS : nombre d'explosions en cours.
  • STEP X & Y : varier l'angle des diagonales en modifiant STEPY, accélérer le jeu en augmentant les 2. (Au-dessus de Y = 12 & X = 3, absolument injouable).
  • VJOY : répétition de la boucle de déplacement et d'affichage du sprite joystick. Le programme accomplira VJOY déplacements avant de repasser la main aux envahisseurs.
  • VAUTO : idem que VJOY mais pour les envahisseurs. Dans la mesure où il est impossible de s'en tirer si les envahisseurs sont plus rapides que vous, (essayez pour voir !...), ce paramètre restera à 1.
  • VMISS : idem pour les missiles. Si VMISS < = VJOY, vous risquez d'entrer en collision avec eux.

Note. Tout abus sur ces 3 paramètres (>5) entraîne une animation saccadée.

  • NBSPMAX : le nombre total d'envahisseurs à gérer. Initialement 20 sprites. Ce nombre peut être diminué sans problème. Pour l'augmenter, ajouter autant de nouveaux blocs à TABLESP. Moins il y en a, plus le programme se déroule rapidement. Au-aessus de 30 sprites, vous commencez à ne plus savoir où vous êtes. Pour plus de 30, créez une table avec des sprites plus petits d'un tiers pour ne pas surcharger l'écran et avoir une vitesse de jeu acceptable.
  • NBSPACTI : le nombre d'envahisseurs en service. Utilisé par le programme.
  • ADSPTAFF : permet au programme de connaître directement Padresse de début du bloc gestion du sprite en cours de traitement. (Evite de recalculer cette dernière si on en a besoin à un moment donné).
  • POSMIS : début des 4 blocs de gestion relatifs aux 4 missiles. La position de ces derniers dépendant de la position du sprite joystick, les adresses POSMIS & COINMIS n'ont pas a être initialisées.
  • TABLEMIS : les octets composant votre missile. (Mini table de sprites). Vous pouvez modifier forme et couleur au missile ici même. Si vous modifiez aussi les dimensions, pensez à retoucher aussi HAUTMI5S & LONGMISS pour les 4 missiles. Des dimensions trop importantes ralentiront considérablement le jeu lors des tirs.
  • NBMISS : permet au programme de connaître le nombre de missiles en cours de traitement.
  • TABLEMIN : comme TABLEMIS mais pour les mines.
  • HAUTMINE & LONGMINE : dimensions des mines. Ces dernières étant toutes identiques et n'ayant pas à être déplacées, elles n'ont pas esoin de blocs gestion spécifiques.
  • SPAFFICH : permet à QUELSPT de savoir de quel sprite il s'agit. (De 1 à 20 : envahisseur, 0 : sprite joystick, 255 : missile). Suggestion : ajouter en entrée de QUELSPT une comparaison sur 1 qui dérivera sur une routine de collision identique aux autres sauf qu'elle décrémentera un compteur N avant de considérer le sprite comme détruit et il faudra toucher l'envahisseur Num. 1 N fois pour s'en débarrasser. Sur le même principe, on peut avoir des sprites indestructibles, des réactions particulières aux collisions... Cette variable est la clé de voûte de QUELSPT, ne la négligez pas dans vos essais !
  • POSCOL : garde en mémoire l'adresse écran où a lieu la collision. Utilisé par QUELSPT.
  • SPTAUTO : le début de la table de gestion des envahisseurs.
  • HLSPTAUTO : dans le cas où certains sprites sont de taille différente (missiles), il est utile de conserver les dimensions courantes dans un endroit rapidement accessible. Si vous modifiez le programme pour utiliser une table à dimensions variables, c'est encore plus utile.
  • ADSPTJOY : pour récupérer rapidement l'adresse du sprite joystick DANS LA TABLE DE SPRITES.
  • SPTADRES : début d'une zone de 10 octets où est recopié par LDIR (TABLEPROG) le bloc de gestion du sprite en cours de traitement. Evite de jongler avec des "LD registre , (IX + NN)" lorsque l'on a d esoin d'un paramètre précis.
  • CONTROLE : utile seulement aux utilisateurs d'assembleurs. Après le premier assemblage, faites : "? PEEK(38459) + 256*PEEK(38450)" si le résultat est différent de 12345, il y a immanquablement des fautes de frappe (code objet trop long ou trop court).

DIVERS

Suppressions et résurrections = incrémentations et décrémentations de compteurs. Les mêmes opérations se répétant suite aux boucles basées sur VMIS-VAUTO-VJOY, il pourrait bien se produire une décrémentation de trop. Dans ce cas le compteur passerait de 0 à 255. D'où les tests d'entrée sur 0 à l'entrée de chaque routine importante.

La pose des mines et le tir des missiles nécessitent un décalage d'adresse écran par rapport au sprite qui les génère. Sinon le test de collision serait immédiatement positif. Ce décalage impose un test de validité séparé sur les limites écran. La fréquence de pose des mines est fixe (255).
Pour le reste, les commentaires du listing devraient suffire. Le principe des Boucles principales est résumé en 5 croquis. Seul l'essentiel y figure.

FAITES-VOUS LES DENTS

Modifications possibles : créez vos propres tables. Du moment qu'elles sont à intervalles fixes et en mode 0, le programme peut théoriquement digérer n'importe quoi. (Sauf si table > 2200 octets, auquel cas, il faut la loger ailleurs et revoir les adressages directs du programme). Pour utiliser des tables en mode 1, il faut modifier les tests pixels de la collision, missiles - mines. Tant qu'à faire, changez aussi les données pixels de ceux-ci. (Voir variables). Changez quelque peu la taille des missiles ou des mines. (C'est assez simple).

Utilisez l'option 5 de SURGENE pour créer une table, où la superposition de plusieurs dessins donne l'illusion d'un mouvement. Ceci fait, exploitez la variable ETATSPT avec une routine du genre EXPLOSE. Elle devra être appelée à chaque tour de MOVEAUTO et modifiez le contenu de ADSPTAF. Vos envahisseurs battront ainsi des ailes. (Pas facile du tout).

Restructurez le programme pour qu'il accepte des tables à intervalles variables. (Pas trop dur mais beaucoup de travail).
Modifiez le nombre maximum des missiles (enfantin).

Modifiez la section NEWINVAD (raccourcir) de manière à provoquer leur réapparition au point où ils ont été abattus (évident).
Créez des envahisseurs de classe particulière du genre indestructible, pondeur (se multiplient lorsqu'ils sont touchés), croiseur (ne changent pas de direction lorsqu'ils rencontrent un obstacle, autre que la bordure écran), inoffensif (ne peuvent vous détruire), etc. (difficile et surtout très long).

Ce programme pèse moins de 5K tout mouillé. Développez-le jusqu'à ce qu'il remplisse toute la mémoire, puis ceci fait, utilisez la technique du splitting pour qu'il remplisse toute la disquette. (Au fou !).

LE PROGRAMME BLOODY.BAS

Il exploite une bonne partie des possibilités du binaire. Vous avez 3 vaisseaux au départ. Les paramètres vitesses relatives, mode de tir, nombre d'envahisseurs sont initiali-sés de manière aléatoire. Certaines combinaisons seront injouables. Vous pourrez les refuser mais cela vous coûtera des points. A vous de découvrir les plus favorables. Attention, si la vitesse de votre vaisseau est supérieure ou égale à celle des missiles, tirer en vous déplaçant, risque d'entraîner votre destruction. Un point à chaque fois qu'une mine est touchée.
10 points pour un envahisseur abattu.

Tous les points * 10 si tous les envahisseurs sont abattus.

Un vaisseau de rab pour chaque tranche de 1000 points. Un seul tableau complété peut rapporter de 2 à 5 vaisseaux.

CPC n°34 - Mai 1988

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

Page précédente : Graphic - CPC 33 - Animation et Gestion de Sprites - Deplacement Multi - Sprites - Test de Collision

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

Lien(s):
» Coding Src's » Graphic - Farbspielereien - Colors (CPC Amstrad International)
» Coding Src's » Sprite Handling Routines (Jason Brooks)
» Coding Src's » Graphic - Controlling Patterns
» Coding Src's » Bola Multicolor (Amstrad User)
» Coding Src's » Graphic - Rosette (CPC Amstrad International)
» Coding Src's » Graphic - Vector Graphics (The Amstrad User)
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 277 millisecondes et consultée 2266 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.