|
|||||||||||||||||||||||||||||||||||||||||||
|
Annoncée le mois dernier, en sus de l'initiation à AMOS que tient dorénavant son auteur en personne, j'ai nommé François Lionet, voici une nouvelle rubrique dans Commodore Revue qui vous apprendra à créer vos propres jeux. L'AMOS a été choisi pour illustrer ces articles grâce aux facilités qu'il offre pour la gestion des BOB, sprites, bruitages, musiques, etc. Cette rubrique restera toutefois assez généraliste, vous permettant ainsi d'adapter vos nouvelles connaissances à d'autres langages - BASIC, C ou Assembleur. Pac-Rev et Com-Roid sont dans un bateau... Le but de cette rubrique n'est pas de vous donner toutes les routines nécessaires à la création du jeu du siècle, mais plutôt tous les éléments essentiels à la réalisation d'un jeu, quel qu'il soit. Car en effet, que vous programmiez un Lode Runner, un Battle Chess ou un Pendu, les bases restent les mêmes, seules changent les règles du jeu. Ce premier article sera essentiellement théorique ; nous y aborderons des notions importantes (comme la synchronisation vidéo, le double tampon mémoire, etc.) qui ne seront pas reprises par la suite. Nous vous engageons donc plus que vivement à le lire avec énormément d'attention. Nous nous lancerons ensuite lentement mais sûrement dans la réalisation d'un Pac-Man. Oh bien sûr, nous n'en développerons que le squelette, laissant à votre sagacité le soin de créer de nouveaux tableaux et de nouvelles difficultés. Il en ira de même pour le casse-briques du plus pur style Arkanoid que nous construirons par la suite, ainsi que du jeu de tir inspiré de Xenon qui sera l'objet de notre quatrième rendez-vous. Séquentialité et multitâche L'Amiga est multitâche, je ne vous apprends rien. Cela signifie qu'il est capable d'exécuter plusieurs programmes en même temps, vous permettant par exemple d'écouter la cinquième de Beethoven tout en écrivant une lettre à votre grand-mère ou en dessinant la pin-up de vos rêves. C'est d'ailleurs peut-être ce qui a motivé votre achat (sans parler de ses qualités graphiques et sonores, cela va de soi). Alors si j'arrive avec mes gros sabots et en vous apprenant sans prendre de précaution que vous vous êtes fait lamentablement berné, vous allez certainement m'en vouloir... Pourtant, le fait est là : votre Amiga n'est capable de n'exécuter qu'un seul programme à la fois. Le multitâche version Amiga n'est que supercherie : on l'obtient grâce à certaines astuces de programmation, en exécutant chaque programme l'un après l'autre, suffisamment rapidement pour donner l'illusion que tout fonctionne en même temps. Quel rapport avec les jeux, vous demanderez-vous ? Simplement celui-ci : même dans les plus gros succès que vous puissiez posséder - Shadow Of The Beast, Battle Squadron et autres - chaque personnage, chaque vaisseau, chaque boulet de canon est déplacé séquentiellement, c'est-à-dire suivant un ordre bien précis et défini par le programmeur du jeu. Pour prendre un exemple plus concret : dans Shadow Of The Beast, le décor ne défile pas pendant que le personnage court, mais avant. L'ordre des actions effectuées par l'ordinateur dans ce cas est : 1. faire défiler le décor ; 2. afficher le personnage. Encore une fois, si cela est fait suffisamment rapidement, l'illusion de simultanéité des deux événements est parfaite. Ce sera notre première notion essentielle : la séquentialité. La seconde notion essentielle découle de ce qui vient d'être dit : la rapidité. Synchronisation Avez-vous déjà remarqué, lorsque vous déplacez une fenêtre dans l'écran du Workbench, que le cadre "fantôme" censé représenter son contour n'est pas toujours complètement affiché, suivant que le déplacement se situe dans la partie supérieure de l'écran ou dans sa partie inférieure ? Il en "manque" tantôt le haut, tantôt le milieu, tantôt le bas. Ce phénomène que les anglicistes nomment "flickering" est connu chez nous sous le nom de "scintillement". Il est dû à un problème de synchronisation de l'affichage avec le balayage du rayon électronique qui produit l'image sur le moniteur. Pour simplifier le problème, disons que ce rayon est comme un pinceau qui peindrait l'image sur le moniteur d'après les données qu'il trouverait dans la mémoire de l'ordinateur. Son travail est répétitif et régulier : il commence par représenter la première ligne sur l'écran, puis la seconde, la troisième, et ainsi de suite jusqu'à la dernière, pour ensuite "remonter" vers le haut de l'écran et tout recommencer, le tout à une fréquence de 50 Hz, soit 50 images par seconde. Arrivé à ce stade, il convient de bien différencier les termes "écran" et "moniteur". Dans cette série d'articles, le mot écran représentera toujours l'image telle qu'elle est codée dans la mémoire de l'ordinateur, c'est-à-dire sous forme d'octets de 8 bits. Le mot "moniteur" désigne quant à lui l'appareil qui permet de visualiser cet écran, comme le 1084S de Commodore ou, plus modestement, le poste de télévision. Imaginez maintenant que ce rayon électronique ait déjà représenté la moitié de l'image et que l'on décide d'afficher un objet quelconque dont la hauteur sera égale à celle de l'écran. Que va-t-il se passer ? Simple : l'Amiga va dessiner l'objet dans sa mémoire graphique, cette même mémoire que le rayon électronique balaye ; ce dernier continuant sont travail indépendamment de ce que peut bien faire l'ordinateur, il va soudainement trouver dans cette mémoire une moitié d'objet - celle appartenant à la moitié d'écran pas encore balayée - qu'il va tout simplement afficher avec le reste. Si l'on pouvait geler l'image à ce moment-là, on ne verrait qu'une moitié de l'objet dans le bas de l'écran ; la moitié supérieure ne sera quant à elle représentée qu'au prochain passage du rayon dans le haut de l'écran. C'est ce qui provoque ce scintillement désagréable. De cela on déduit que si l'on pouvait attendre que le rayon ait complètement balayé l'écran entier avant d'y dessiner quoi que ce soit, tout nouvel objet serait entièrement affiché en un seul passage du rayon. Cette attente est bien évidemment possible, et elle est notre troisième notion essentielle : la synchronisation. Double tampon mémoire Vous en avez peut-être déjà entendu parler, de cette technique du double tampon mémoire, mais les explications que vous avez pu lire à droite et à gauche ne sont sans doute pas très claires. Il est vrai que, comme l'a dit je ne sais plus quel grand homme, les choses les plus simples sont souvent les plus difficiles à expliquer. Le double tampon mémoire est une extension de la synchronisation. Son utilité tient du fait qu'il n'est pas toujours possible, notamment dans les jeux les plus complexes où beaucoup d'objets doivent être affichés, de modifier l'image entière en un seul passage du rayon électronique. On obtient alors de nouveau et pour les mêmes raisons le phénomène de scintillement. Pour y remédier, on va devoir jongler avec un deuxième écran virtuel dans la mémoire de l'ordinateur. Évidemment, un seul de ces deux écrans sera visible sur le moniteur, ce qui permet de dessiner tous nos objets dans le second écran. Une fois celui-ci terminé, on attend la synchronisation et on demande à l'ordinateur de l'afficher sur le moniteur, pendant que l'on continue nos dessins dans le premier écran (devenu à ce moment-là invisible) et ainsi de suite. De cette manière, aucun scintillement n'est plus possible. 50 images par seconde ! Rappelez-vous ce qui a été dit plus haut : le rayon électronique balaye l'écran 50 fois par seconde. En d'autres termes, il affiche 50 images par seconde. Or, lorsque que le programme est suffisamment bien fait, c'est-à-dire avant tout suffisamment rapide (tout dépend bien entendu de la complexité du jeu), la technique de synchronisation vidéo seule est suffisante pour produire une animation parfaite, elle aussi à cinquante images par seconde. Dans le cas du double tampon mémoire, l'animation est ralentie de moitié, puisqu'un seul passage du rayon ne suffisant plus, il faut en attendre un second avant d'afficher l'image modifiée. Un rapide calcul mental indique donc que la fréquence d'animation tombe à 25 images par seconde. Cette fréquence est à comparer avec celle d'un film au cinéma : ce sont 24 images par seconde qui sont projetées et le mouvement est toujours très net. Il est par contre totalement déconseillé d'attendre un troisième passage de rayon : la fréquence tomberait alors à 16 images par seconde... soit à peine plus que les 12 images par seconde des meilleurs dessins animés japonais. L'Amiga est tout de même capable de faire un peu mieux que ça, non ? Et AMOS dans tout ça ? S'il est possible de réaliser (plus ou moins) facilement une animation au cinquantième en Assembleur ou en C, qui est un langage compilé, cela est beaucoup moins évident en BASIC, qui reste un langage interprété et en tant que tel, est obligé de tester, pour chaque instruction, si les paramètres fournis sont valides, puis d'appeler la routine correspondant à cette instruction, ce qui consomme autant de temps. Ceci est évidemment (et malheureusement) valable pour AMOS, pour lequel, à part dans quelques cas vraiment très simples, l'animation au cinquantième est à exclure. C'est pourquoi il est préférable de s'habituer dès maintenant à la technique du double tampon mémoire, qui produira toujours une animation fluide. AMOS possède heureusement tout ce qu'il faut pour ça. Ces remarques risquent évidemment de devenir caduques dès lors que le compilateur AMOS sera sorti, ce qui ne devrait plus tarder maintenant. Mais pour l'instant, nous nous bornerons à utiliser l'interpréteur d'AMOS, dans la version que vous possédez actuellement. Vous trouverez en annexe un exemple de déplacement de dix BOB en double tampon mémoire selon deux méthodes, l'une "automatique" (AMOS se charge de tout), l'autre "manuelle" (on se tape tout le boulot nous-mêmes), histoire de vous permettre de vous familiariser avec cette technique et avec les instructions d'AMOS propres à sa gestion. Par curiosité, retirez la commande "Double Buffer" du premier listing... Et n'hésitez surtout pas à le modifier selon votre bon plaisir, car n'oubliez pas le proverbe breton : "c'est en se mouchant que l'on devient moucheron". ![]() ![]()
|