![]() |
Programmation | ![]() |
||
UFO | ||||
![]() |
Images - Listing - Téléchargement - Vidéo - Bonus | ![]() |
||
Un jeu en 10 lignes MSX Basic |
||||
En 2010, en l'honneur des 25 ans du MSX, le site de Konamito proposait un concours de programation de jeu sur MSX. Un classique en soi mais là le jeu ne devait tenir qu'en 10 lignes de programation Basic seulement! Sachant que chaque ligne ne peut contenir plus de 255 caractères et interdit l'utilisation de poke pour le langage machine la tache semble bien compliqué, voir impossible. Le défi a pourtant été relevé par de nombreux programmeur dont votre serviteur avec UFO.
|
||||
L'idée |
||||
Une nouvelle fois l'inspiration me viendra d'un jeu en ligne pratiqué par mon fils. Un jeu ou une DCA tente d'entraver l'avance de ballons dirigeables bombardant ses positions, de nombreuses options permettent de faire évoluer son armement, celle-ci seront les bienvenues pour affronter les vagues ennemie ssans cesse plus nombreuses et plus puissantes! Pour la version MSX en 10 lignes Basic le jeu sera profondément épuré. Pas d'options, tir droit et pas en angle mais on choisit toujours l'endroit où se produira l'explosion de son missile. Au début le jeu devait s'appeler DCA mais son évolution l'a transformé en un UFO. Les graphismes des monstres ne me convenait pas. Je les ai alors remplacé par des ovnis au look plus rétro et cadrant mieux avec le décor. Les vies se sont aussi transformées en une tour de contrôle bombardée. |
![]() |
Quelques Images | ![]() |
||
![]() |
![]() |
![]() |
||
Le "pré- projet" | L'écran d'accueil | Touché! | ||
![]() |
|
UFO | ![]() |
|
||||
![]() |
Ligne 1 | ![]() |
||
Initialisation du jeu, avec choix de mode ecran, création et mise en place des graphismes. Rien de spécial dans ce début de programmme si ce n'est le choix du screen1 en mode sprite 8x8 pour plus de facilité graphique. | ||||
![]() |
UFO | ![]() |
||
1 SCREEN1,0:DIMC,X,Y,P,W(9):WIDTH32:COLOR3,12,1:KEYOFF:FORI=14350TO14381:READA$:VPOKEI,VAL("&h"+A$):NEXT: FORI=32TO87:READA$:VPOKEI,VAL("&h"+A$):NEXT:FORI=6240TO6815:VPOKEI,0:NEXT:VPOKE8192,177:VPOKE8193,97: FORI=1TO38:READA,B:VPOKE6300+A,B:NEXT
|
||||
![]() |
Ligne2 | ![]() |
||
Préparation de l'écran d'attente avant début du jeu, où on initialise les variables et l'ecran avant un prochain jeu. | ||||
![]() |
UFO | ![]() |
||
2 DEFINTA-Z:PLAY"","t250s8m6000o4l2dd+dcd4","T200O3L2D.DD":LOCATE2,22:PRINT"U.F.O. SCORE: 0 MAX:";M: X=40:Y=96:C=0:ONSPRITEGOSUB8:VPOKE6785,7:VPOKE6753,7:VPOKE6721,7:VPOKE6689,7:VPOKE6657,6:FORI=0TO9: X(I)=0:C(I)=0:W(I)=0:P(I)=0:PUTSPRITEI,,0,0:NEXT
|
||||
![]() |
Ligne 3 | ![]() |
||
Initialisation des registres son, de la valeur aléatoire et on tourne en boucle jusqu'à l'appui sur une touche. Petite astuce: La formule Q=1+1*(STRIG(0)=-1) permet de définir le mode de contrôle suivant que "espace" ou le bouton 1 a été enfoncé, en fait par défaut Q vaut 1 tant qu'on a pas appuyé sur "espace". |
||||
![]() |
UFO | ![]() |
||
3 SOUND7,48:SOUND6,0:Z=RND(-TIME):LOCATE5,1:PRINT"PUSH SPACE OR SWITCH 1 ! ":Q=1+1*(STRIG(0)=-1): IFSTRIG(Q)=-1THENFORI=6176TO6232:VPOKEI,32:NEXT:V=5:P=4:PLAY"v11","t250v9s8m6000o4L2dd+dcl4dd-dl2ee+ec2l4ee","t250v10o3l2d.d-dcl4dd+dl2ee-ec2l4e"ELSE3
THEN ...
FORI=6176TO6232:VPOKEI,32:NEXT: Effacement du message PUSH SPACE...
V=5:P=4: Initialisation des variables, V (vies) à 5 et P à 4.
PLAY"v11","t250v9s8m6000o4L2dd+dcl4dd-dl2ee+ec2l4ee","t250v10o3l2d.d-dcl4dd+dl2ee-ec2l4e" ...musique d'intro.
ELSE3 Sinon on reprend au début de la ligne
|
||||
![]() |
Ligne 4 | ![]() |
||
Déplacement du viseur et gestion des déclenchement des tirs sur une boucle tournant 3 fois de 7 à 9 , plans d'affichage des sprites.C(I) gère la couleur du tir et et permet aussi de détecter l'activation du tir ou non. | ||||
![]() |
UFO | ![]() |
||
4 D=8*(S=3)*(X<224)-8*(S=7)*(X>24):E=16*(S=5)*(Y<112)-16*(S=1)*(Y>32):Y=Y+E:X=X+D:PUTSPRITE21,(X,Y),13,3: PUTSPRITE20,(X,159),10,4:IFSTRIG(Q)=0THENH=0ELSEIFH=0THENH=1:FORI=7TO9:IFC(I)<2THENW(I)=Y:X(I)=X:Y(I)=152: C(I)=2:P(I)=1:I=9:PLAY"o4f32":NEXTELSENEXT
THENH=0...alors tempo(H) à 0...
ELSEIFH=0...sinon si tempo(H) à 0...
THENH=1:...alors tempo(H) à 1...
FORI=7TO9:...début de la boucle des 3 tirs...
IFC(I)<2...Si statut tir n'est pas en cours...
THENW(I)=Y:...enregitrement niveau de l'explosion...
X(I)=X:...enregitrement du X du tir...
Y(I)=152:...enregitrement du Y du tir...
C(I)=2:...statut tir actif...
P(I)=1:...N° sprite = tir...
I=9:...on force la fin de la boucle...
PLAY"o4f32"...on joue le son tir...
NEXT...fin de la boucle...
ELSENEXT...sinon fin de la boucle...
|
||||
![]() |
Ligne 5 | ![]() |
||
Gestion des tirs toujours sur une boucle de 7 à 9. Là C(i) permet de définir le statut du tir, en cours, explosion, fin et sert de tempo pour l'explosion tout en en changeant la couleur donnant une impression d'animation de celle-ci. | ||||
![]() |
UFO | ![]() |
||
5 FORI=7TO9:IFC(I)>1THENY(I)=Y(I)+8*(P(I)=1):PUTSPRITEI,(X(I),Y(I)+1),C(I),P(I):IFY(I)=W(I)THENP(I)=5:W(I)=0:PUTSPRITEI,(X(I),Y(I)+1),C(I),P(I) :C(I)=3:PLAY"t250o4e64"ELSEIFC(I)>2THENC(I)=C(I)+1:IFC(I)=10THENC(I)=1:P(I)=0:PUTSPRITEI,(0,0),0,0
THENY(I)=Y(I)+8*(P(I)=1):...alors Y tir monte si N° sprite = tir...
PUTSPRITEI,(X(I),Y(I)+1),C(I),P(I):...affichage du sprite tir...
IFY(I)=W(I)...Détection si tir atteind le niveau de l'explosion...
THENP(I)=5:...alors N°sprite = explosion...
W(I)=0:...niveau explosion à 0...
PUTSPRITEI,(X(I),Y(I)+1),C(I),P(I):...affichage du sprite explosion...
C(I)=3:...couleur sprite (tempo explosion) à 3...
PLAY"t250o4e64"...on joue le son explosion...
ELSEIFC(I)>2...sinon si tempo explosion actif...
THENC(I)=C(I)+1:...alors incrémentation tempo explosion...
IFC(I)=10...si tempo explosion finit...
THENC(I)=1:...alors fin cycle tir/explosion...
P(I)=0...N° sprite tir à 0...
PUTSPRITEI,(0,0),0,0...Effacement du sprite explosion...
|
||||
![]() |
Ligne 6 | ![]() |
||
Gestion des 6 ovnis avec une boucle de 0 à 5. le programme vérifie si on a perdu sinon on continue le jeu. Petite astuce: On commence par fermer avec un NEXT la boucle de la ligne précédente, ça permet de palier les ratages du aux IF...THEN... de la ligne précédente. La variable C(i) gère à la fois la couleur de l'ennemi et sa vitesse. |
||||
![]() |
UFO | ![]() |
||
6 NEXT:IFV=0THENV=8:PLAY"","t180o3b","t180o2b":GOTO10ELSEFORI=0TO5:IFX(I)=<8THENIFC(I)=0THENX(I)=240: C(I)=INT(1+RND(1)*(3+INT(C/500))):C(I)=5*-(C(I)>5)-C(I)*(C(I)<6)ELSEC(I)=0:GOSUB10ELSEY(I)=32+I*16:
PUTSPRITEI,(X(I),Y(I)),C(I)+4,2:X(I)=X(I)-C(I)
THENV=8:...alors le compteur vie est mis à 8 pour gestion du game over...
PLAY"","t180o3b","t180o2b":..on joue une petite musique de fin...
GOTO10...Et on saute à la ligne 10...
ELSEFORI=0TO5:...sinon on lance la boucle "UFO"...
IFX(I)=<8...on teste si l'ovni a atteind le bord de l'écran...
THENIFC(I)=0...alors si l'ovni n'est plus affiché (couleur à 0)...
O=I:...Sauvegarde du plan de sprite actif pour affichage de l'explosion de la tour...
THENX(I)=240: ...alors on remet l'ovni à droite... C(I)=INT(1+RND(1)*(3+INT(C/500))):...on choisi l'ovni (vitesse/couleur) au hasard et suivant le score (C)...
C(I)=5*-(C(I)>5)-C(I)*(C(I)<6)...on limite le niveau de l'ovni...
ELSEC(I)=0:...sinon effacement de l'ovni...
GOSUB10...et on va au sous-programme de gestion de perte de vie en 10... ELSEY(I)=32+I*16:...sinon on définit la hauteur de l'ovni...
PUTSPRITEI,(X(I),Y(I)),C(I)+4,2:...on affiche l'ovni...
X(I)=X(I)-C(I) ...et on déplace l'ovni vers la gauche. |
||||
![]() |
Ligne 7 | ![]() |
||
On commence une nouvelle fois par fermer la boucle de la ligne précédente et on retourne en ligne 4 pour fermer la boucle principale. La ligne est courte, on en profite pour y mettre un max de datas qui peuvent être mis n'importe où dans le jeu. | ||||
![]() |
UFO | ![]() |
||
7 NEXT:SPRITEON:S=STICK(Q):GOTO4:DATA18,18,00,18,24,ff,7e,3c,42,00,66,00,00,00,00,00,00,66,18,18,18,18,42,7e,a5,db, ba,7c,d9,7e,3a,55,00,00,00,00,00,50,20,50,20,20,a8,70,df,70,a8,20,00,91,9a,9c,ae,97,98,66,ff,99,99,ff,ff,99,99,ff,01,02,04,08, 10,20,40,80
|
||||
![]() |
Ligne 8 | ![]() |
||
La ligne qui gère les collisions de sprites. Ici on ne s'occupe que des collisions entre explosions et ovnis car c'est le seul cas posssible en dehors de 2 explosions ensemble, voir "Le petit truc en plus" pour plus d'info. On lance une boucle pour les ovnis et une pour les tirs et on teste pour chaque s'il y a destruction de l' ovni ou pas. | ||||
![]() |
UFO | ![]() |
||
8 SPRITEOFF:FORL=0TO5:FORK=7TO9:IFP(K)<5THENNEXT:NEXT:RETURNELSEIFY(K)=Y(L)ANDX(K)>X(L)-9ANDX(K)<X(L)+9THEN PUTSPRITEL,(0,0),0,0 :X(L)=0:C(K)=9:C=C+C(L)*10:C(L)=0:LOCATE15,22:PRINTC:PLAY"t250o5l64e":K=9: DATA80,40,20,10,08,04,02,01,00,00,00,00,00,3c,7e,ff
THENNEXT:...alors on teste le tir suivant...
NEXT: ...Quand on a fini de tester les tirs on passe à l'ovni suivant... RETURN ...Quand on a fini de tester les tirs et ovnis on retourne au programme principal. ELSEIFY(K)=Y(L)ANDX(K)>X(L)-9ANDX(K)<X(L)+9 ...Sinon si les coordonées ovni et explosion correspondent... THEN PUTSPRITEL,(0,0),0,0: ... Effacement du sprite ovni...
X(L)=0: ...Position horizontale de l'ovni à 0. C(K)=9: ...Mise à la valeur de fin de cycle du temporisateur de l'explosion... C=C+C(L)*10: ... Incrémentation du score en fonction de l'ovni abattu; ovni plus rapide= score plus élevé.... C(L)=0: ... Mise à 0 de la valeur de l'ovni... LOCATE15,22: ...Placement du curseur au niveau du score pour écriture... PRINTC: ...Affichage du score... PLAY"t250o5l64e": ...On joue le bruitage de l'explosion. K=9: ...On "sort" de la boucle tir.
|
||||
![]() |
Ligne 9 | ![]() |
||
On commence une nouvelle fois par fermer les boucles des lignes précédentes et on retourne au programme principal. Une ligne qui fourmille de data gérant en premier l'emplacement ou sera mis le décor écran (-6300) et en second celui qui sera mis à cet emplacement, voir ligne1. | ||||
![]() |
UFO | ![]() |
||
9 NEXT:NEXT:RETURN:DATA99,4,78,4,147,4,248,4,265,4,305,4,381,4,484,7,486,7,513,7,490,8,459,8,428,8,397,8,366,8,367,9,400,
9,433,9,496,8,465,8,434,8,435,9,468,9,501,9,506,8,507,9,509,8,478,8,479,9,512,9,452,10,454,10,481,10,102,5,225,5,21,5,407,5,182,5
|
||||
![]() |
Ligne 10 | ![]() |
||
Gestion des pertes de vies et de la fin du jeu avec affichage du Game Over , petite musique de fin et enregistrement du score max. Ici c'est la musique qui sert de tempo avant le retour à l'écran d'acueil. Le compteur de vie sert de variable de statut du jeu. | ||||
![]() |
UFO | ![]() |
||
10 IFV=8THENLOCATE12,1:PRINT"GAME OVER !":V=9:PLAY"","cdd-ddl2ee+ecl4ee","c.dd-ddl2ee+ecl4e." :GOTO10ELSEIFV=9THENM=-M*(C<=M)-C*(C>M):IFPLAY(0)=0THEN2ELSE10ELSEV=V+1*(V>0):VPOKE6785-V*32,0: PUTSPRITEO,(8,162-V*8),10,5:PLAY"t250o3l32gf":RETURN
THENLOCATE12,1: ...Alors placement du curseur en haut pour écriture...
PRINT"GAME OVER !": ...Affichage du Game Over !. V=9: ...Incrémentation de la variable de détection de stade jeu en jeu = perdu et géré... PLAY"","cdd-ddl2ee+ecl4ee","c.dd-ddl2ee+ecl4e.": ...Musique de fin... GOTO10 ...Retour en début de ligne ELSEIFV=9...Sinon si le jeu est perdu et géré... THENM=-M*(C<=M)-C*(C>M): ... Sauvegarde du meilleur score grace à une formule magique...
IFPLAY(0)=0 ...Si la musique de fin est finie.... THEN2 ...Retour à l'accueil...
ELSE10 ... Sinon retour à la ligne (attente)... |
||||
![]() |
Téléchargement: | ![]() |
||
Fichier zip comprenant le fichier disquette et le fichier texte du programme. UFO.zip | ||||
![]() |
UFO | ![]() |
||
![]() |
La vidéo: |
![]() |
||
![]() |
UFO | ![]() |
||
|
||||
![]() |
Le petit truc en plus... |
![]() |
||
La gestion des collisions de sprites. Les interruptions provoquées par les collisions provoquent de forts ralentissements, pour palier à une surcharge excessive du programme, on joue sur la forme et le déplacement des sprites. Le viseur en violet ne rencontre ni le tir en jaune ni l'ovni en bleu qui ne se rencontrent pas l'un l'autre grace à leurs formes mais aussi à leurs déplacements (de 8 en 8 pour le viseur et le tir). Il en va de même pour l'explosion. Seuls une explosion et un ovni peuvent se superposer ce qui déclenche un appel au sous programme de gestion des collisions en ligne 8.
Toutefois un autre cas peut se présenter, il s'agit de deux explosions se déclenchant au même endroit, de plus ce cas a tendance à "boucler" du fait que les sprites ne disparaissent pas tout de suite. Ce désagrément est atténué par le fait que le joueur n'a que très peu d'intéret à tirer 2 fois de suite au même endroit et l'impossibilité de tirer en "rafale". ![]() ![]() |
||||
![]() |
UFO | ![]() |
![]() |
![]() |
|||
![]() |
||||
![]() |
Made in Osaure | ![]() |