Dans tous les jeux vidéo que vous voyez sur Amiga, vous verrez beaucoup de Sprites et de Bobs, ces personnages à l'écran qui glissent sur les décors, se tirent dessus ou courent dans des labyrinthes à la recherche de quelques heures de détente. Ces personnages à l'écran sont appelés sprites pour une raison perdue depuis longtemps dans l'histoire de la programmation informatique.
Au fond de ma mémoire, je me rappelle vaguement quelque chose à propos d'insectes appelés esprits de l'eau (« water sprites »), et de la manière dont ils glissent à la surface de l'eau. J'imagine un programmeur Atari regardant ces choses glisser partout et se demandant s'ils ne cherchaient pas à lui dire quelque chose sur la façon dont les aliens devraient se déplacer sur la surface d'un décor sans le toucher. Jusque-là, tous les personnages à l'écran écrasaient et redessinaient l'arrière-plan derrière eux en se déplaçant, car ils habitaient le même plan graphique.
Quoi qu'il en soit, même si cette histoire d'esprits de l'eau est bidon (j'aime bien comment ça sonne), les Sprites sont maintenant intégrés dans le matériel de tout ordinateur capable de faire tourner des jeux, et sont généralement appelés Sprites matériels (« hardware sprites »). Ce sont des blocs graphiques distincts qui sont séparés de l'affichage principal, sur un plan séparé pourrait-on dire, de sorte qu'ils glissent à la surface de l'arrière-plan sans le perturber. L'Amiga dispose de huit Sprites matériels, et ceux-ci étaient le top en 1985.
Mais lorsque l'Amiga a été conçu, ils ont aussi inclus une fonction appelée Blitter Objects ou Bobs. Ceux-ci sont meilleurs que les Sprites pour deux raisons importantes :
Les Bobs, en revanche, utilisent la puce Blitter de l'Amiga, capable de copier des images à l'écran à une vitesse d'un million de pixels par seconde. Les Bobs sont comme des Sprites, mais sans aucune limite. Ils peuvent avoir autant de couleurs et de résolutions que les écrans Amiga, et ils peuvent être aussi nombreux que vous le souhaitez car il n'y a aucune limitation de nombre. Bien sûr, plus vous avez de Bobs à l'écran, plus vous sollicitez le processeur, mais ne vous en faites pas. Il est rare que vous poussiez AMOS aussi loin avec vos programmes. Gardez cependant à l'esprit que les Bobs sont plus lents que les Sprites et utilisent plus de mémoire. Cela peut être une considération même pour les petits programmes.
Les Sprites sont limités en taille, et leur palette ne peut contenir que les 16 dernières couleurs d'un affichage en 32 couleurs. Donc si la palette du Sprite prend certaines de ses couleurs dans les 16 premières, ces couleurs changeront selon les arrière-plans. Il faut faire très attention lors de la création de Sprites.
En règle générale, utilisez les Bobs pour des formes lentes et de grande taille, et les Sprites pour des formes rapides et de petite taille, c'est un bon partage des tâches.
C'est facile, avec tout ce discours sur les Sprites et les Bobs, de finir par s'y perdre un peu. Quand vous voyez un personnage à l'écran dans un jeu, on l'appelle toujours un sprite, mais c'est un terme générique, et ce n'est pas censé signifier que l'objet est un Sprite ou un Bob. Comme les aspirateurs et les stylos bille, le mot commence par une minuscule et désigne tout objet en mouvement à l'écran. Quand je parle de routines spécifiques etc., faites attention à ce dont il est précisément question. Je vais essayer d'être clair, mais vous devrez vous concentrer, c'est votre part du contrat.
Une autre chose, les Sprites peuvent être rendus plus grands que la limite de 16 pixels, en utilisant ce qu'on appelle dans AMOS des Sprites calculés. L'ordinateur colle automatiquement des Sprites ensemble pour en faire des Sprites plus grands. Vous pouvez aller jusqu'à 128 pixels de large, car il n'y a que huit Sprites matériels. (Tsk ! Rien que des limitations !)
Créer ses propres Sprites est très facile. Vous pouvez capturer un Sprite depuis une image IFF en utilisant la commande GET SPRITE (et quelques effets spéciaux très sympas peuvent être obtenus de cette manière), mais de loin la meilleure méthode est d'utiliser un éditeur de Sprite comme Sprite Editor.AMOS depuis vos disquettes AMOS, ou mieux encore SpriteX. (Voir le chapitre 10 pour plus de détails)
Les Sprites peuvent être conçus et dessinés directement dans SpriteX ou simplement capturés depuis un fichier IFF. C'est pratique car vous vous sentirez peut-être plus à l'aise pour dessiner dans DPaint ou quelque chose de ce genre plutôt que de plonger directement dans un moteur de sprites inconnu.
Une fois que le Sprite ou le Bob a été dessiné et capturé, il peut être enregistré dans un fichier ABK sur disque, puis chargé dans des programmes AMOS pour être utilisé. Une grande attention doit être portée à la création des Sprites afin d'utiliser les bonnes couleurs pour la palette que vous allez employer. Pour conserver la même palette dans DPaint entre deux images, il suffit de charger l'image dont vous voulez la palette, de la vider, puis de dessiner vos sprites et de les sauvegarder. La palette sera alors identique à celle de votre image. (Gardez également à l'esprit ce que j'ai dit à propos des Sprites utilisant les 16 dernières couleurs dans une palette de 32 couleurs !)
Il est possible d'utiliser l'animation sans utiliser AMAL, et avec les progrès d'AMOS, comme par exemple l'AMOS Compiler, de telles routines n'ont pas besoin d'être lentes. Une fois compilés, les mouvements peuvent être aussi rapides et fluides qu'avec AMAL, et dans certains cas, selon la façon dont vous écrivez et structurez (optimisez en d'autres termes) votre code, ils peuvent même être aussi rapides sans compilation.
Une animation simple peut être réalisée en changeant rapidement l'image dans une commande Bob ou Sprite, comme ceci :
Rem * Bob Animation.AMOS * Rem Load "Sprites.abk" : Rem Chargez ici votre fichier de sprites préféré Main: Bob 1,100,100,1 Wait Key Bob 1,100,100,2 Wait Key Bob 1,100,100,3 Wait Key Bob 1,100,100,4 Wait Key Goto Main
Ce cas vous montre que vous pouvez visualiser chaque image d'une Sprite et créer une animation à partir de celle-ci. Chaque fois que vous appuyez sur une touche, l'animation avance d'une image, et bien que cela soit très agréable, l'animation est habituellement un peu plus rapide que cela. Pour animer les images correctement, il vous suffit d'ajouter une boucle au processus :
For A=1 To 10 Bob 1,100,100,A Wait Vbl Next A
La commande Wait Vbl adoucit l'animation en attendant le prochain blanc vertical de l'écran avant de passer à l'image suivante. Vous pouvez changer le Wait Vbl en un Wait n avec n=5 ou quelque chose comme ça. Cela ralentit l'animation à une vitesse raisonnable. Les images sont défilées de 1 à 10 (la plupart des animations sont un peu moins complexes que cela) et suffisamment rapidement pour donner l'illusion du mouvement. Si vous voulez savoir comment faire de l'animation proprement dite... eh bien, c'est un sujet plus important, suffisant pour un livre entier. Procurez-vous un livre sur la réalisation de films d'animation et appliquez les techniques qui y sont décrites, ou pourquoi ne pas obtenir une copie de The Animation Studio de Disney Software, qui contient beaucoup de très bons tutoriels sur la façon de dessiner une animation.
L'élément clé de l'animation est d'animer uniquement lorsque c'est nécessaire. Très peu de Sprites nécessitent une animation en permanence, et la plupart ne s'animent que lorsqu'elles se déplacent. Si vous avez besoin d'une animation constante alors je suppose qu'AMAL est la meilleure idée, car tout fonctionne indépendamment du code AMOS. Cela peut toutefois être un inconvénient dans certains cas, en particulier lorsque vous devez faire passer des informations entre AMOS et AMAL, et si vous prévoyez de compiler le programme je dirais d'éviter AMAL.
Essayez donc d'animer en mouvement, ce qui signifie que, par exemple, si votre petit homme ou autre doit se déplacer vers la gauche, alors une Sprite le montrant marchant vers la gauche est utile. Vous n'avez pas besoin de dessiner tous les mouvements de la Sprite (en particulier si la Sprite a la même apparence des deux côtés), car vous pouvez retourner la Sprite de gauche à droite en ajoutant un nombre hexadécimal $800 à la définition de la Sprite. Voilà pour la création et l'animation. Et qu'en est-il du déplacement et des collisions ?
Déplacer des Sprites et des Bobs sans AMAL est très simple. Les Sprites peuvent être propulsés sur l'écran n'importe où, simplement en ajustant les coordonnées x,y sur l'écran. Ces nombres peuvent être augmentés (INC) ou diminués (DEC) ou utilisés dans une boucle FOR NEXT jusqu'à n'importe quelle valeur, et contrôlés par n'importe quel contrôleur externe comme la souris ou le joystick, ainsi que par de nombreux autres types de contrôle comme nous le verrons au chapitre 11 sur les contrôles et les mouvements. Essayez donc ceci :
Rem * Movit.AMOS * Rem Load "sprites.abk" : Rem n'oubliez pas de charger vos sprites préférés For Z=1 to 80 Bob 1,X,80,1 Next Z
Il vous suffit donc de modifier les coordonnées sur l'écran, et cela ne doit pas nécessairement être une simple boucle. Vous pouvez ajuster le point auquel un Bob est tracé sur l'écran en douceur ou par saccades, et ces positions peuvent provenir de n'importe quoi, même du son de la musique jouée en arrière-plan, comme avec les commandes VUBARS.
Sauf si ce que vous faites avec AMOS n'est pas un jeu en soi, vous voudrez détecter les collisions. Il ne sert à rien d'avoir des Sprites qui foncent sur l'écran si vous ne pouvez pas dire quand deux ou plusieurs d'entre eux se heurtent, ou lorsque l'un tire, que les autres vont exploser.
Il y a deux aspects dans la détection des collisions entre Sprites ou Bobs :
BOBCOL
, SPRITEBOBCOL
, BOBSPRITECOL
ou SPRITECOL
, qui détectent si des Sprites se sont heurtés. Autrement dit « quelqu'un a-t-il touché quelque chose ? »COL()
qui teste pour voir quel sprite individuel a subi des dommages, ou « qui a touché quoi ? »Par exemple, si votre héros est le Sprite 8 et que les méchants sont les Bobs 1, 2, 3 et 4, vous feriez quelque chose comme ceci :
C=Spritebobcol(8,1 To 4)
ce qui renvoie une valeur de -1 si vous avez touché l'un des Bobs mentionnés, et 0 si vous ne l'avez pas fait. Il vous faut donc un test après la commande pour tester IF THEN -1
ou 0 GOTO
un autre endroit.
Le premier autre endroit est la fonction COL()
, comme ceci :
If Col(3) Then Print "Crash"
ou plus appropriément GOTO
les images d'animation pour une explosion et les remplacer à la place du Sprite actuel. Voici un programme qui explique tout cela très simplement :
Rem * Collision Detect.AMOS * Rem Screen Open 0,320,200,16,Lowres Curs Off : Flash Off : Hide : Cls 0 Load "df0:sprite_600/aliens/alien1.abk" Load "df0:sprite_600/space/ship3.abk",1 Get Sprite Palette Double Buffer Bob 1,0,80,0 Bob 2,320,80,1 Shared M M=320 Do _ANIMSHIP _MOVEALIEN If Bob Col(1) Then _BOOM Loop Procedure _MOVEALIEN M=M-5 Bob 2,M,80,1 End Proc Procedure _ANIMSHIP For Y=18 To 21 Bob 1,, ,Y Wait Vbl Next Y End Proc Procedure _BOOM Boom For X=35 To 43 Bob 1,0,80,X Wait 4 Next X Wait Key End Pen 6 : Paper 0 : Centre "Bang! You're dead!" End Proc
Ce programme présente un certain nombre de fonctionnalités qui méritent d'être examinées. Évidemment, les Sprites proviennent du jeu de Sprites "Sprite 600", disponible sur vos disquettes AMOS ou via l'un des divers points de distribution AMOS PD. Ce sont les mêmes Sprites que ceux utilisés dans le jeu AMAL simple que j'ai décrit dans les chapitres AMAL, en fait il s'agit d'une sorte de prototype de cette idée.
Dans cet exemple, le vaisseau spatial attend sagement à l'extrémité de l'écran, et vous ne pouvez pas le déplacer du tout. Le vaisseau alien arrive par la droite de l'écran, et lorsque le vaisseau est touché par l'alien, il explose magnifiquement.
Toutes les informations d'image pour les explosions, etc., sont contenues dans les fichiers de Sprites, et comme dans d'autres exemples qui utilisent les fichiers de Sprites d'exemple, les Sprites sont chargés les uns après les autres dans la même banque de Sprites. Si vous souhaitez rendre ce programme un peu plus facile à gérer (et éviter l'attente lors du chargement des Sprites depuis le disque), vous devriez les charger en mode direct et les sauvegarder avec le programme. Ou, pour être vraiment gentil, vous pouvez charger les fichiers de Sprites dans la banque en les fusionnant en ajoutant le nombre positif à la fin du nom de fichier, puis sauvegarder la banque sur le disque en tant que nouveau fichier ABK.
Une fois les Sprites chargés, nous activons DOUBLE BUFFER
pour éviter tout scintillement des Sprites, et GET SPRITE PALETTE
garantit que nos Sprites conservent les bonnes couleurs. Dans ce cas, les Sprites proviennent du même ensemble, donc ils utilisent tous les mêmes couleurs. Si vos Sprites ont des palettes différentes, vous devrez peut-être les rééditer et modifier les palettes pour les adapter.
Ensuite, nous définissons les positions initiales des Bobs, puis nous définissons une variable comme shared
pour la position du Bob dans la procédure appelée _MOVEALIEN
. La raison pour laquelle cette variable est partagée est que la procédure est appelée chaque fois que le Bob est déplacé, donc la variable doit être définie en dehors de la procédure. Si la variable n'est pas partagée, alors elle est toujours égale à 0, car elle n'est jamais définie, selon la procédure. Cela signifie que le Sprite apparaîtrait soudainement à la même position que le vaisseau et ferait exploser le vaisseau immédiatement, au lieu de traverser doucement l'écran.
Nous sommes donc prêts. La boucle principale du programme est la boucle DO LOOP
, qui tourne indéfiniment jusqu'à ce que la combinaison Ctrl-C soit pressée. La boucle exécute les principales parties du programme, appelant des procédures puis revenant au début. Chaque fois qu'elle appelle la procédure _MOVEALIEN
, l'alien se déplace vers la gauche. (J'ai ajouté un caractère de soulignement au début des noms de procédures pour pouvoir utiliser n'importe quel mot, au lieu de me limiter à des noms qui ne sont pas des commandes ou mots réservés !) Chaque fois que la procédure _ANIMSHIP
est appelée, la flamme de queue du vaisseau s'anime. Et à la fin de la procédure, nous avons la routine de détection de collision qui déclenchera la procédure appelée _BOOM
lorsque l'alien entrera en contact avec le vaisseau.
La procédure _BOOM
joue un bruit d'explosion puis anime la séquence d'explosion depuis la banque de Sprites. Cela ne fonctionnera que si les Sprites sont ceux spécifiés, car ils possèdent des images spécifiques dans la banque qui remplissent des fonctions précises.
Le mouvement du sprite est un peu saccadé, même avec le double buffering. Mais vous pouvez améliorer cela avec une organisation soignée. Par exemple, n'animer que les éléments qui en ont besoin est une bonne pratique. L'astuce à la Paul Daniels fonctionne aussi bien, c'est-à-dire la distraction. Si votre Sprite se déplace rapidement et dans tous les sens, personne ne remarquera vraiment qu'il est un peu saccadé, n'est-ce pas ? Cela fonctionne bien aussi avec les écrans défilants : s'il se passe quelque chose sur l'écran, ce sera moins évident. La planification est essentielle, mais évidemment tous ces problèmes disparaissent en grande partie lorsque vous compilez un programme.
Une autre méthode consiste à vérifier si un élément ayant une animation constante est en mouvement, et dans ce cas à arrêter les boucles qui pourraient le ralentir. Définissez une variable comme interrupteur (toggle) entre deux valeurs lorsque certains processus sont en cours, puis vérifiez simplement ce qui fonctionne et, si vous en avez plus qu'un certain nombre, vous pouvez en fermer quelques-uns. C'est une façon complexe de procéder, mais cela fonctionne.
Voici comment basculer une variable entre deux valeurs :
S=2 Do Print S S=12-S Loop
Cela bascule une variable appelée S entre 2 et 10, en la rendant égale à 12 moins sa valeur actuelle. Comme elle est égale à 2 une fois, puis 10 l'autre fois, elle oscille entre 10 et 2. Malin, non ?
L'une des choses les plus difficiles à faire lorsqu'on travaille avec des Sprites, en particulier ceux des autres, est de savoir quelle image dans la banque correspond à quoi. Mais si vous y réfléchissez, il est remarquablement facile de créer un petit programme qui parcourt une banque pour vous et vous montre de manière interactive ce qui s'y trouve.
Pour vérifier les caractéristiques vitales de vos banques de Sprites, laissez ce programme faire tout le travail :
Rem * Sprite Bank Viewer.AMOS * Rem F$=Fsel$("*.abk","","Load sprite bank","to show on screen") If F$="" Then End Load F$ Flash Off : Curs Off : Get Sprite Palette N_SP=Length(1) For N=1 To N_SP-1 A=Sprite Base(N) If A Clw Bob 1,100,100,N Print "Sprite number";N Print "Size in X:";Deek(A)*16 Print "Size in Y:";Deek(A+2) Print "Number of bitplanes:";Deek(A+4) Print "Position of hot spot in X:";Deek(A+6) Print " Y:";Deek(A+8) End If Wait Key Next
Ce programme permet de sélectionner une banque de Sprites à visualiser via une boîte de dialogue, puis affiche chaque Sprite un par un avec ses caractéristiques techniques : dimensions, nombre de plans de bits, et position du point chaud.
Chaque fois que vous appuyez sur une touche, après avoir chargé le fichier de Sprites en question, le programme passe à l'image suivante et vous donne une lecture des caractéristiques importantes de l'image : numéro, largeur, hauteur, etc.
En guise d'exercice, essayez de créer une variante de ce programme qui permettrait de naviguer dans les deux sens à travers les Sprites.
Une sorte de compétence spécifique dans la création de jeux consiste à gérer la création, le suivi et les collisions des projectiles, même en grand nombre. C'est un gros problème, mais avec un peu de mathématiques intelligentes, on peut le résoudre sans trop de difficultés.
Cette routine a été créée à l'origine par Aaron Fothergill du AMOS Club, et elle est présentée ici car c'est l'une des plus claires et efficaces que j'aie vues :
Rem * Multi-bullet.AMOS * Rem Dim BX(10),BY(10),BDY(10),BS(10) Curs Off : Flash Off : Cls 0 : Paper 0 : Pen 1 : Ink 2,2 Bar 0,0 To 7,15 : Hide On Get Bob 1,0,0 To 16,16 : Hot Spot 1,4,0 For A=0 To 9 Cls 0 : Locate 0,0 : Pen A+2 : Print "*" Get Bob 2+A,0,0 To 16,8 : Hot Spot 2+A,4,4 Next A X=160 : Y=180 Cls 0 : Double Buffer : Colour 2,$FFF : Colour 1,$FF0 Fade 1,$0,$FFF,$F00,$F0,$F,$FF0,$FF,$F0F,$F80,$8F0,$F8,$8F,$80F,$F08 While Mouse Key<2 Bob 1,X,Y,1 If NB>0 Then Gosub BULLETS GTG=1-GTG : X=X Screen(X Mouse) If Mouse Key=1 Then Gosub FREBULLET Wend End BULLETS: For A=0 To NB-1 Bob 2+A,BX(A),BY(A),2+BS(A) BX(A)=BX(A)+1 : BY(A)=BY(A)+BDY(A) If GTG=0 Then BDY(A)=Min(A,BDY(A)+1) Next A NB2=NB For A=NB-1 To 0 Step -1 If BY(A)>199 or BX(A)<0 or BX(A)>319 Bob Off 1+NB2 Swap BX(A),BX(NB2-1) Swap BY(A),BY(NB2-1) Swap BDY(A),BDY(NB2-1) Swap BS(A),BS(NB2-1) Dec NB2 End If Next A Return
La beauté de cette routine est qu'elle ne perd pas de temps avec les projectiles qui ne sont plus en mouvement, et trie les projectiles restants de manière à ce qu'ils soient plus efficaces. Diabolique.
En plus de tout le reste, le programme crée d'abord les Bobs que nous allons utiliser, et dans ce cas il s'agit d'un genre de feu d'artifice qui se déplace de gauche à droite en fonction des mouvements de votre souris. Si vous appuyez sur le bouton de la souris, les étincelles jaillissent de l'extrémité du feu d'artifice. Les projectiles et leurs mouvements sont stockés dans des tableaux, et lorsque le bouton de la souris est pressé, la routine de tir est activée et plusieurs projectiles sont propulsés vers le haut en suivant une courbe influencée par la gravité.
Étudiez les procédures BULLET
et FREBULLET
et leur fonctionnement. Utilisez la commande SWAP
pour trier les projectiles en fonction de leur statut.
Le pointeur de la souris dans AMOS est un Sprite, tout comme le logo AMOS en haut de l'écran dans l'éditeur. Ceux-ci sont tous stockés dans une banque spéciale appelée Mouse.abk
sur vos disquettes AMOS. Dans cette banque spéciale :
Vous pouvez charger et éditer ces Sprites mais vous devez conserver la même résolution et le même nombre de couleurs, sinon AMOS plantera. Les curseurs sont tous en 2 plans de bits (4 couleurs) en Hires, et le logo AMOS est en 4 plans de bits (16 couleurs). Restez dans ces limites et vous pourrez créer votre propre ensemble de pointeurs personnalisés.