Space Aliens
GW-Basic, utilisé par PC-Basic
Programme avec Graphique et Texte
Un autre classique issu de l'âge d'or des salles d'arcade est Space Invaders (1978).
Ce jeu répondait à une
question essentielle : et si les blocs de la zone d'évasion bougeaient et
pouvaient vous tirer dessus ?
Vous contrôlez un vaisseau spatial,
positionné en bas de l'écran, qui peut se déplacer horizontalement et tirer sur
les extraterrestres envahisseurs, généralement disposés en cinq rangées de onze.
Ces aliens, obstinément déterminés, forment une vague qui descend lentement mais inexorablement vers le bas de l'écran.
Ils vous tirent parfois dessus également ; vous abriter derrière les bunkers défensifs verts, stratégiquement placés, vous protège… jusqu'à ce que ces bunkers soient détruits par suffisamment de tirs.
Mais si les aliens
atteignent le bas de l'écran, la partie est terminée.
L'ouvrage Game
On! : Video Game History from Pong and Vac-Man to Mario, Minecraft, and More de
Dustin Hansen attribue la conception et le développement de ce jeu légendaire à
un seul homme : Tomohiro Nishikado.
« Non seulement Nishikado a créé les graphismes et le gameplay de Space Invaders », explique Hansen, « mais il a passé un an à développer le matériel nécessaire au fonctionnement du jeu, en assemblant un ordinateur de A à Z. »
Space Invaders, poursuit Hansen, était incroyablement novateur, proposant de nombreuses premières dans le monde du jeu vidéo :
un système de scores élevés, la sauvegarde des scores des joueurs, la gestion d’une « horde sans fin » d’ennemis, la nécessité d’éviter les tirs ennemis et une bande-son dynamique (et angoissante).
Bien sûr, SPACE.BAS n'est pas un clone de Space Invaders, mais c'est le programme qui, parmi tous ceux présentés dans cette section se rapproche le plus de l'expérience d'un jeu d'arcade original, malgré quelques bugs.
Et son fonctionnement diffère légèrement selon que vous utilisiez la version Windows de PC-BASIC, la version Mac ou le GW-BASIC authentique ; il vous faudra ajuster le code pour une expérience optimale).
Vous pilotez votre
vaisseau avec les touches A et S, et tirez au laser (ou au canon ?) avec la
barre d'espace. Bonne chance pour nous sauver des envahisseurs extraterrestres !
Comme pour CHOMPER.BAS, la complexité du
jeu nous oblige à analyser le code progressivement.
Dans un premier
temps, les extraterrestres ont été dessinés avec
GRID.BAS.
Chaque extraterrestre possède une animation de deux images.
Les animations des extraterrestres ont été copiées presque pixel par pixel à partir de captures d'écran de Space Invaders.
Une fois les fichiers séquentiels générés par GRID.BAS, ils ont été concaténés et nettoyés (espaces superflus supprimés) à l'aide d'un éditeur de texte.
Voici le code des animations des extraterrestres ; comme vous le constaterez rapidement, il ne comporte que quelques lignes à saisir.
Lignes 15 - 1255
Nous utiliserons également GRID.BAS pour générer le code du vaisseau spatial :
Lignes 1300 - 1540
Nous n'aurons cependant pas besoin de GRID.BAS pour dessiner la balle/le laser tiré par le canon du vaisseau spatial :
Lignes 1550
Ensuite : un écran titre, reprenant les instructions de jeu de base à l’utilisateur.
Lignes 1551 - 1558
Maintenant, vidons l'écran et peuplant-le de quelques rochers vert foncé — qui, tôt ou tard, encaisseront leur part de coups d'armes et subiront des dégâts considérables.
Lignes 1570 - 1590
Nous allons maintenant déclarer et initialiser une série de tableaux pour les extraterrestres.
Ces tableaux permettront de suivre le nombre d'extraterrestres encore en vie (élément = 1) et morts (élément = 0) sur chaque ligne d'invasion.
Lignes 1600 - 1640
Avant d'aller plus loin, il faut coder plusieurs sous-routines.
Tout d'abord, il faut récupérer les données saisies par l'utilisateur au clavier ; comme d'habitude, une instruction INKEY$ est nécessaire.
Lignes 3000 - 3100
Lorsque la barre d'espace est enfoncée, la ligne 3095 ordonne à GW-BASIC de sauter vers une sous-routine qui tire un projectile (ou un laser) depuis le vaisseau spatial.
Notez que la ligne 3245
ci-dessous utilise l'instruction POINT pour vérifier si le projectile (ou le
laser) a touché la face inférieure d'un rocher (dessiné, rappelons-le, en vert
foncé, couleur 2) ; si c'est le cas, un morceau du rocher est détruit.
Notez également que la ligne 3247 ci-dessous effectue une vérification de
collision du projectile (ou du laser) impactant un extraterrestre (tous les
extraterrestres sont rendus en blanc, couleur 15) ; si une collision est
détectée, le programme est renvoyé à la ligne 3500, au début d'une autre
sous-routine que nous détaillerons prochainement.
Lignes 3200 - 3255
Ensuite, nous allons créer une sous-routine qui tire sur le vaisseau spatial grâce à la puissance de feu extraterrestre.
Cette sous-routine détectera toute collision entre le projectile (ou le laser) et le vaisseau (ligne 3355) — infligeant la mort au joueur si le vaisseau est touché — ainsi qu'entre le projectile (ou le laser) et le rocher (ligne 3350).
Lignes 3300 - 3365
En additionnant les valeurs stockées dans les cinq tableaux de lignes extraterrestres, nous pourrons déterminer si tous les extraterrestres ont été détruits.
Lignes 3400 - 3460
Ensuite, il nous faut trouver un moyen de :
(1) afficher les extraterrestres et le vaisseau ;
(2) déplacer les extraterrestres de façon périodique, à gauche, à droite et (lentement) vers le bas ;
et (3) prendre en compte les impacts de balles (ou de lasers) sur divers objets, tout en veillant à ce que le joueur dispose de suffisamment de vies pour poursuivre sa noble, mais probablement vaine, quête visant à repousser l’invasion extraterrestre.
Nous nous appuierons sur les sous-routines codées précédemment, ainsi que sur les tableaux de lignes représentant les extraterrestres, pour accomplir cette tâche.
Lignes 1980 - 2400
Il ne reste plus qu'une chose à faire :
programmer une sous-routine pour vérifier quel extraterrestre a été touché par une balle (ou un laser).
Bien que le code soit court, il est plus complexe qu'il n'y paraît.
Lignes 3500 - 3600
Tous les extraterrestres sont dessinés en blanc.
Par conséquent, utiliser
simplement l'instruction POINT pour détecter l'impact d'une balle sur un pixel
blanc ne permet pas d'identifier l'extraterrestre touché, mais seulement de
constater qu'un extraterrestre a été touché.
Pour déterminer quel
extraterrestre a été touché, il faut superposer chaque extraterrestre sur une
grille invisible, mobile et dynamique de 10x10, puis vérifier si une balle (ou
un laser) atterrit dans l'une des cellules de cette grille contenant des
extraterrestres.
C'est précisément ce que font les instructions conditionnelles ci-dessus : elles vérifient si une colonne de « cellules extraterrestres » a été touchée par une balle (ou un laser) ; la boucle garantit que toutes les colonnes d'extraterrestres sont inspectées. Ce n'est ni rapide ni élégant, mais c'est efficace.
SPACE.BAS
Vous vous demandez peut-être
comment les coordonnées des cellules de la grille imaginaire ont été obtenues.
Un petit utilitaire, appelé LOCATE.BAS, a été utilisé.
Lors de son exécution, LOCATE.BAS ne supprime volontairement pas l'écran et ne modifie pas le mode graphique.
Ce programme affiche simplement un curseur clignotant de la taille d'un pixel et ses coordonnées à l'écran.
À l'aide du pavé numérique, vous pouvez déplacer le curseur et afficher ses coordonnées.
Pour obtenir les coordonnées de la grille imaginaire des extraterrestres, j'ai sauvegardé puis exécuté SPACE.BAS et appuyé immédiatement sur la touche Pause dès leur apparition.
J'ai ensuite exécuté LOCATE.BAS pour déterminer leurs positions initiales précises.
Une fois que vous aurez écrit suffisamment de programmes graphiques complexes en GW-BASIC, l'utilité de LOCATE.BASIC vous semblera évidente.
Plutôt que de tâtonner pour obtenir les coordonnées souhaitées à l'écran, exécutez LOCATE.BASIC et épargnez-vous bien des maux de tête.
10 REM LOCATE - Move
cursor using numeric keypad to locate coordinates on-screen
12 KEY
OFF:SCREEN 7:COLOR 15,0:CLS
15 DIM CURSOR(2)
20 PSET(1,1),15
30
GET(1,1)-(1,1),CURSOR
40 PSET(1,1),0
50 X=100:Y=100
60 I$=INKEY$
65 PUT(X,Y),CURSOR,XOR
66 FOR PAUSE=1 TO 100:NEXT PAUSE
67 PUT(X,Y),CURSOR
70 IF I$="4" THEN X=X-1
80 IF I$="6" THEN X=X+1
90 IF I$="8" THEN Y=Y-1
100 IF I$="2" THEN Y=Y+1
110 IF I$=CHR$(27) THEN END
120 LOCATE
1,1:PRINT"(";X;",";Y;")"
130 GOTO 60
Une fois que vous aurez
programmé suffisamment de programmes graphiques complexes en GW-BASIC, l'utilité
de LOCATE.BAS vous semblera évidente. Plutôt que de tâtonner pour obtenir les
coordonnées souhaitées à l'écran, exécutez LOCATE.BAS et épargnez-vous bien des
maux de tête.
Bien que SPACE.BAS offre une expérience de jeu de type
Space Invaders plutôt correcte, de nombreux aspects pourraient être améliorés.
L'écran titre, par exemple : il ne contient que du texte, et un texte
terriblement ennuyeux et peu engageant. Autre point à améliorer : la détection
des collisions, notamment celles entre les extraterrestres et les tirs du canon
du vaisseau. De plus, lorsque les extraterrestres tirent sur le vaisseau, d'où
tirent-ils exactement ?
Mais le pire, c'est que le jeu se termine
brutalement une fois le niveau débarrassé de tous les envahisseurs
extraterrestres. Pour une expérience Space Invaders plus authentique, il
suffirait de faire apparaître une nouvelle vague d'aliens – plus intelligents,
plus rapides et plus rusés que les précédents – et de lancer une nouvelle
attaque, à l'infini. Le jeu devrait tourner indéfiniment. Tout comme la
bande-son légendaire, qui, bien sûr, est absente de SPACE.BAS.
Mais quoi
que vous fassiez, vous serez probablement frustré par la vitesse de
rafraîchissement des animations et le scintillement qui en résulte – non
seulement dans SPACE.BAS, mais aussi dans des jeux comme CHOMPER.BAS et
METEOR.BAS.
Ces programmes sont des tentatives courageuses, mais finalement infructueuses, de contourner les limitations systémiques de GW-BASIC en tant qu'interpréteur ligne par ligne.
Puisque ces programmes ne sont pas traduits en code machine en une seule fois, mais par morceaux, le processus est considérablement ralenti, car GW-BASIC, tel un Sherlock Holmes, est contraint d'inspecter séquentiellement chaque ligne de code à la loupe, alors même que les programmes sont déjà en cours d'exécution.
Ce genre de comportement, associé à un code peu optimisé (ou difficilement optimisable) dès le départ, pourrait sonner le glas du langage. Mais ce n'est certainement pas la seule raison.