Section courante

A propos

Section administrative du site

But du jeu

Voici le jeu Nibbles, le jeu de serpent s'allongeant et qu'il ne faut pas avoir d'impact avec un votre serpent ou le serpent de l'ordinateur. Chaque fois que vous avez un impacte, l'ordinateur gagne un point et chaque fois que l'ordinateur à un impact, vous avez un 1 point. Il n'existe pas vraiment de fin au jeu à proprement parler. Ainsi, lorsque vous avez plus de point que l'ordinateur, vous pouvez considéré que vous avez gagné.

Le jeu Nibbles consiste à bloquer le joueur l'ordinateur (ligne rouge) à l'intérieur de votre ligne (vous êtes la ligne jaune) afin qu'il ne puisse plus bouger. Pour y arriver, vous tracer des lignes dans toutes les directions de façon à limiter l'espace qu'il peut accéder. Le jeu réclame une carte vidéo VGA (soit le mode vidéo _MRes256Color correspondant à 320x200 pixels en 256 couleurs) et utilise uniquement le clavier pour déplacer le joueur.

Déplacement

La procédure ChoiceSpeed permet de fixer la vitesse de déplacement de la ligne, plus le chiffre est bas, plus la vitesse de déplacement est base, tandis que plus la chiffre est gros, plus le déplacement est rapide. Pour arriver une vitesse de déplacement confortable et par soucis de compatibilité avec le matériel plus récent, on utilise une fonction de délai plutôt qu'un WaitRetrace (attente d'un rafraîchissement vertical de l'affichage vidéo). Ainsi, la procédure WaitRetrace pointe directement sur la procédure DELAY de l'unité CRT.

Après un certain laps de temps, le serpent s'allonge d'un point vers la direction courante (le tableau RX direction horizontale et le tableau RY pour la direction verticale). Votre joueur est la cellule 1 et l'ordinateur est la cellule 2 des tableaux. Vous pouvez connaître la position actuelle de votre joueur de l'ordinateur en consultant les tableaux X (horizontale) et Y (verticale).

Traçage de ligne

Les lignes sont traçages de façon à faire un rotation de 8 palettes de couleur rouge ou jaune en fonction du joueur. La programmation des deux palettes de couleur se fait à l'aide de la fonction _RemapPalette. chaque déplacement d'un point, le couleur change d'un palette supérieur et revient à zéro après la huitième palette de couleurs. Pour cette raison, étant données la grande quantité de couleur utilisé, le jeu test à l'aide de la fonction _GetPixel que la couleur n'est pas noir (soit la valeur 0) afin de déterminer si impacte s'est produit.

Le jeu exploite l'unité graphique MSGraph pour l'affichage du jeu, lequel n'est pas présent sous Turbo Pascal. Il n'est donc pas possible d'exécuter ce jeu sous Turbo Pascal sans modifier profondément le code. Malheureusement, l'unité Graph proposé par Borland est beaucoup plus limité que celle de QuickPascal et c'est la raison pour laquelle le jeu a été écrit en QuickPascal d'abord.

Initialisation

Au début du jeu, la position de l'ordinateur et de votre joueur sont choisis de façon aléatoire (en utilisant la fonction RANDOM), mais afin que vous ne perdez immédiatement ou que l'ordinateur ne perdent pas immédiatement, la coordonnées est vérifié afin qu'elle ne correspondent pas à l'autre joueur. Si elle correspond à l'autre joueur, une nouvelle coordonnées est choisis.

Le QuickPascal ne supporte pas les procédures Break et Continue, pour cette raison, l'utilisation de Goto et Label devient donc la solution alternative pour compenser ce manque de ce langage de programmation.

Lors de la sélection de la vitesse de 1 à 10, une fonction appel CenterStr permet d'ajouter des espaces de façon à avoir des espaces avant et après le message et après de manière à ce qu'il soit au milieu. Grâce à cette technique, on a l'impression qu'une barre de sélection est déplacer lorsqu'on fait un choix.

Contrôle du joueur

Le QuickPascal ne propose pas de procédure événement pour détecté que des touches sont tapez au clavier. On doit donc vérifier à l'aide de la fonction KeyPressed qu'une touche est enfoncé au clavier et on utilise la fonction ReadKey, basé sur la fonction DOS et non BIOS pour déterminé la touche enfoncé. La fonction BIOS de lecture du clavier (Interruption 16h, fonction 00h). Résultat, la fonction ReadKey demande deux appelés pour vérifier que des touches de flèches sont enfoncés. Ainsi, si la code renvoyé par ReadKey la première fois vaut 0, il faut lire un deuxième code afin de déterminé la touche enfoncé. Si la premier code n'est pas 0, il s'agit soit d'un Esc, Enter ou d'une lettre, de chiffre ou d'un symbole du clavier.

Le jeu inclue l'unité MOUSE.PAS étant un pilote démonstrateur fournit avec le QuickPascal permettant de jouer avec la souris au jeu. Mais la souris n'apporte pas d'avantage à ce jeu, il n'est donc pas vraiment utilisé.

Code source

Le code source QuickPascal du jeu :

  1. Program Nibbles;
  2.  
  3. Uses Crt,MSGRAPH,Mouse;
  4.  
  5. Const
  6.  MaxYZone=183;
  7.  
  8.  {Code de touche clavier renvoy,e par ReadKey}
  9.  kbNoKey=0;{Pas de touche}
  10.  kbEsc=$001B;{Escape}
  11.  kbUp=$4800;{Up}
  12.  kbLeft=$4B00;{FlSche de gauche (Left)}
  13.  kbRight=$4D00;{FlSche de droite (Right)}
  14.  kbDn=$5000;{FlSche du bas (Down)}
  15.  kbHome=$4700;{Home}
  16.  kbTab=$0F09;{Tabulation}
  17.  kbEnd=$4F00;{End}
  18.  kbEnter=$000D;{Enter}
  19.  
  20. Type
  21.  CenterType=(__Left__,__Justified__,__Right__);
  22.  
  23.  RGB=Record
  24.   R:Byte;                       { (R)ouge ((R)ed) }
  25.   G:Byte;                       { (V)ert ((G)reen) }
  26.   B:Byte;                       { (B)leu ((B)lue) }
  27.  End;
  28.  
  29. Const PalYellow:Array[0..7]of RGB=(
  30.  (R:$FC-70;G:$FC-70;B:$24-35),
  31.  (R:$FC-60;G:$FC-60;B:$24-30),
  32.  (R:$FC-50;G:$FC-50;B:$24-25),
  33.  (R:$FC-40;G:$FC-40;B:$24-20),
  34.  (R:$FC-30;G:$FC-30;B:$24-15),
  35.  (R:$FC-20;G:$FC-20;B:$24-10),
  36.  (R:$FC-10;G:$FC-10;B:$24-5),
  37.  (R:$FC;G:$FC;B:$24));
  38.  
  39. Const PalRed:Array[0..7]of RGB=(
  40.  (R:$FC-70;G:0;B:0),
  41.  (R:$FC-60;G:0;B:0),
  42.  (R:$FC-50;G:0;B:0),
  43.  (R:$FC-40;G:0;B:0),
  44.  (R:$FC-30;G:0;B:0),
  45.  (R:$FC-20;G:0;B:0),
  46.  (R:$FC-10;G:0;B:0),
  47.  (R:$FC;G:0;B:0));
  48.  
  49. Const
  50.  CurrText:Byte=0;
  51.  
  52. Var
  53.  Speed:Integer;
  54.  X,Y,RX,RY,PR:Array[1..2]of Integer;
  55.  
  56. Procedure WaitRetrace;Begin
  57.  Delay(10*Speed);
  58. End;
  59.  
  60. Function RGB2Color(R,G,B:Byte):LongInt;
  61. Var
  62.  Value:LongInt;
  63.  X:RGB Absolute Value;
  64. Begin
  65.  Value:=0;
  66.  X.R:=R shr 2;
  67.  X.G:=G shr 2;
  68.  X.B:=B shr 2;
  69.  RGB2Color:=value;
  70. End;
  71.  
  72. Function MaxByte(N,Max:Byte):Byte;Begin
  73.  If(N<Max)Then MaxByte:=N+1
  74.   Else MaxByte:=0
  75. End;
  76.  
  77. Function MinByte(N,Max:Byte):Byte;Begin
  78.  If N>0Then MinByte:=N-1
  79.        Else MinByte:=Max
  80. End;
  81.  
  82. Function  Alpha(a,b:LongInt):LongInt;Begin
  83.  If(a<=b)Then Alpha:=a
  84.  Else Alpha:=b;
  85. End;
  86.  
  87. Procedure CloseCur;Begin
  88.  _SetTextCursor($2000);
  89. End;
  90.  
  91. Function CenterStr(S:String;Width:Byte):String;
  92. Var
  93.  I:Byte;
  94.  Temp:String;
  95. Begin
  96.  Temp:='';
  97.  For I:=1 to (Width-Length(S))shr 1 do Temp:=Temp+' ';
  98.  Temp:=Temp+S;
  99.  While Length(Temp)<Width do Temp:=Temp+' ';
  100.  CenterStr:=Temp;
  101. End;
  102.  
  103. Procedure PutMsg(X:Byte;Msg:String;Kr:Byte);Begin
  104.  _SetTextPosition(24,X);
  105.  _SetColor(Kr and $F);
  106.  _OutText(Msg);
  107. End;
  108.  
  109. Function pCenter(Len:Byte;Center:CenterType):Byte;
  110. Begin
  111.  Case(Center)of
  112.   __Left__:pCenter:=0;
  113.   __Justified__:pCenter:=(40-Len)shr 1;
  114.   __Right__:pCenter:=40-Len;
  115.  End;
  116. End;
  117.  
  118. Procedure PutTxtCenter(Y:Byte;Center:CenterType;Msg:String;Attr:Byte);Begin
  119.  _SetTextPosition(Y,pCenter(Length(Msg),Center));
  120.  _SetColor(Attr and $F);
  121.  _OutText(Msg);
  122. End;
  123.  
  124. Function WordToStr(X:Word):String;
  125. Var
  126.  S:String;
  127. Begin
  128.  Str(X,S);
  129.  WordToStr:=S
  130. End;
  131.  
  132. Procedure Init;Begin
  133.  X[1]:=Random(320);
  134.  Y[1]:=Random(MaxYZone);
  135.  Repeat
  136.   X[2]:=Random(320);
  137.   Y[2]:=Random(MaxYZone);
  138.  Until Not((X[1]=X[2])and(Y[1]=Y[2]));
  139.  RX[1]:=0;RY[1]:=-1;RX[2]:=0;RY[2]:=1;
  140.  _SetBkColor(0);
  141.  _ClearScreen(_GClearScreen);
  142.  PutMsg(0,'Joueur 1: '+WordToStr(PR[1]),236);
  143.  PutMsg(24,'Ordinateur: '+WordToStr(PR[2]),244);
  144. End;
  145.  
  146. Const
  147.  HomeY=8;
  148.  Max=9;
  149.  
  150. Procedure PutBar(Y:Integer);Begin
  151.  GotoXY(8,HomeY+Y);
  152.  TextBackground($A);
  153.  TextColor(0);
  154.  Write(CenterStr(WordToStr(Y+1),24));
  155.  ms_set_pos(0,Y*8);
  156. End;
  157.  
  158. Procedure UndoBar(Y:Integer);Begin
  159.  GotoXY(8,HomeY+Y);
  160.  TextBackground(0);
  161.  TextColor($9);
  162.  Write(CenterStr(WordToStr(Y+1),24));
  163. End;
  164.  
  165. Var D:Byte;
  166.  
  167. Procedure Show;Begin
  168.  Case(D)of
  169.   0:PutTxtCenter(2,__Justified__,'Vitesse',$B);
  170.   8:PutTxtCenter(2,__Justified__,'Vitesse',$E);
  171.  End;
  172.  D:=(D+1)and 15;
  173. End;
  174.  
  175. Procedure ChoiceSpeed;
  176. Label 0;
  177. Var
  178.  XM,YM,K,Count:Word;
  179.  J,Y,Wait,BM:Integer;
  180. Begin
  181.  If ms_init(BM)Then ms_set_vminmax(0,Max*8);
  182.  Repeat
  183.   Y:=0;YM:=0;BM:=0;
  184.   If(_SetVideoMode(_TextC40)=0)Then;
  185.   If _DisplayCursor(False)Then;
  186.   For J:=0to(Max)do UndoBar(J);
  187.   PutBar(Y);
  188.   Wait:=0;
  189.   Repeat
  190.    Repeat
  191.     WaitRetrace;
  192.     Inc(Wait);
  193.     If Wait=4Then Begin
  194.      Show;
  195.      Wait:=0;
  196.     End;
  197.     {If(ms_get_b($FFFF,Count,XM,YM)=0)Then;}
  198.     {If(YM shr 3<>Y)Then Begin
  199. UndoBar(Y);
  200. Y:=YM shr 3;
  201. If Y>Max Then Y:=Max;
  202. PutBar(Y);
  203. End;}
  204.     If BM>0Then Goto 0;
  205.    Until KeyPressed;
  206.    K:=Byte(ReadKey);
  207.    If K=0Then K:=K or (Byte(ReadKey)shl 8);
  208.    Case(K)of
  209.     kbHome:Begin
  210.  UndoBar(Y);
  211.      Y:=0;
  212.  PutBar(Y);
  213.     End;
  214.     kbUp,kbLeft:Begin
  215.      UndoBar(Y);
  216.      Y:=MinByte(Y,Max);
  217.  PutBar(Y);
  218.     End;
  219.     kbDn,kbTab,kbRight:Begin
  220.      UndoBar(Y);
  221.      Y:=MaxByte(Y,Max);
  222.  PutBar(Y);
  223.     End;
  224.     kbEnd:Begin
  225.      UndoBar(Y);
  226.      Y:=Max;
  227.      PutBar(Y);
  228.     End;
  229.     kbEnter:0:Begin
  230.  Speed:=9-Alpha(Y,Max-1);
  231.  Exit;
  232. End;
  233.     kbEsc:Begin
  234.  Speed:=1;
  235.  Exit;
  236. End;
  237.    End;
  238.   Until False;
  239.  Until False;
  240. End;
  241.  
  242. Procedure Play;
  243. Var K,J:Integer;
  244. Begin
  245.  FillChar(PR,SizeOf(PR),0);
  246.  Speed:=1;
  247.  ChoiceSpeed;
  248.  If _SetVideoMode(_MRes256Color)=0 Then Begin
  249.   WriteLn('Mode vidéo non supporté');
  250.   Halt;
  251.  End;
  252.  For J:=0 to 7 do If _RemapPalette(236+J,RGB2Color(PalYellow[J].R,PalYellow[J].G,PalYellow[J].B))=0Then;
  253.  For J:=0 to 7 do If _RemapPalette(244+J,RGB2Color(PalRed[J].R,PalRed[J].G,PalRed[J].B))=0Then;
  254.  Init;
  255.  Repeat
  256.   Repeat
  257.    If _GetPixel(X[1],Y[1])<>0Then Begin
  258.     PutTxtCenter(12,__Justified__,'Vous avez fait l''impacte!',$C);
  259.     {ClrKbd;}
  260.     If ReadKey<>#0 Then;
  261.     Inc(PR[2]);
  262.     Init;
  263.    End;
  264.    If _GetPixel(X[2],Y[2])<>0Then Begin
  265.     PutTxtCenter(12,__Justified__,'L''Ordinateur a fait l''impacte!',$C);
  266.     {ClrKbd;}
  267.     If ReadKey<>#0 Then;
  268.     Inc(PR[1]);
  269.     Init;
  270.    End;
  271.    For J:=1to 2do Begin
  272.     _SetColor(228+(J shl 3)+CurrText);
  273.     _SetPixel(X[J],Y[J]);
  274.    End;
  275.    WaitRetrace;
  276.    CurrText:=(CurrText+1)and 7;
  277.    If RX[2]<>0Then Begin
  278.     If _GetPixel(X[2]+RX[2],Y[2])<>0Then Begin
  279.      RX[2]:=0;
  280.      If _GetPixel(X[2],Y[2]-1)=0Then RY[2]:=-1 Else RY[2]:=1;
  281.     End;
  282.    End
  283.     Else
  284.    If RY[2]<>0Then Begin
  285.     If _GetPixel(X[2],Y[2]+RY[2])<>0Then Begin
  286.      RY[2]:=0;
  287.      If _GetPixel(X[2]-1,Y[2])=0Then RX[2]:=-1 Else RX[2]:=1;
  288.     End;
  289.    End;
  290.    For J:=1to 2do Begin
  291.     Inc(X[J],RX[J]);
  292. Inc(Y[J],RY[J]);
  293.     If RX[J]<>0Then Begin
  294.  If X[J]=0Then X[J]:=319 Else
  295.  If X[J]=319Then X[J]:=0;
  296. End;
  297.     If RY[J]<>0Then Begin
  298.  If Y[J]=0Then Y[J]:=MaxYZone Else
  299.  If Y[J]=MaxYZone Then Y[J]:=0;
  300. End;
  301.    End;
  302.   Until KeyPressed;
  303.   K:=Byte(ReadKey);
  304.   If K=0Then K:=K or (Byte(ReadKey)shl 8);
  305.   If Chr(K)='2'Then K:=kbDn;
  306.   If Chr(K)='4'Then K:=kbLeft;
  307.   If Chr(K)='6'Then K:=kbRight;
  308.   Case(K)of
  309.    kbUp:If RY[1]=0Then Begin;RY[1]:=-1;RX[1]:=0;End;
  310.    kbDn:If RY[1]=0Then Begin;RY[1]:=1;RX[1]:=0;End;
  311.    kbLeft:If RX[1]=0Then Begin;RY[1]:=0;RX[1]:=-1;End;
  312.    kbRight:If RX[1]=0Then Begin;RY[1]:=0;RX[1]:=1;End;
  313.    kbEsc:HALT;
  314.   End;
  315.  Until FaLse;
  316. End;
  317.  
  318. BEGIN
  319.  Randomize;
  320.  Play;
  321. END.

Code source

Voici le code source du jeu sur GitHub :

Lien Langage de programmation Projet
https://github.com/gladir/quickpascal_nibbles/blob/main/NIBBLES.PAS Quick Pascal quickpascal_nibbles


Dernière mise à jour : Dimanche, le 19 décembre 2021