Got an issue with the graph unit in my Pascal program

Viewed 122

I'm new to this forum. I'm here to ask you guys your help. I have an assignment where I have to code a game in Pascal, which is a brick breaker in my case. Though I stumbled upon a problem that I don't quite manage to solve and it's probably related to the graph unit.

It's supposed to display a wall of bricks of various colours in the graphic interface (generated by the graph unit) but nothing appears. The window stays all black. And I know it's not due to having wrtiten a wrong path to the BGI graphic file in the initialisation of the graph unit as I used the same initalisation in an other program where I managed to draw things in the graphic interface.

Finally, my game is in french, so just a few words that you'll need to know: Niveau means level, Jouer means play and Règles means rules. You'll see by choosing a level in the menu that the application will compile but nothing will be displayed in the graph window.

I'd be very glad if you help me out (please).

Here is the main program:

program principal;

uses 
    Crt, Keyboard, sysutils, jeu, graph;

var 
    t : TKeyEvent; 
    c : char; 
    x, y, mur : Integer; 
    F , F2 : Text; 
    V: r; 
    GraphicsDriver, GraphicsMode, ErrCode : Smallint; 
    s : String;
    
begin
    x := 62;
    y := 12;
    GoToXY(47, 4);
    writeln('CASSE BRIQUE STPI EDITION');
    GoToXY(55, y);
    writeln('Niveaux');
    GoToXY(55, y + 2);
    writeln('Regles');
    GoToXY(x, y);

    InitKeyBoard();

    repeat //boucle pour déplacer le curseur de haut en bas dans la première fenêtre du menu
        t := GetKeyEvent();
        t := TranslateKeyEvent(t);
        c := GetKeyEventChar(t);

        if c = 's' then
        begin
            GoToXY(x - 1, y + 2); 
            x := 61;
        end;
    
        if c = 'z' then
        begin
            GoToXY(x, y);
            x := 62;
        end;
    until c = 'm';

    ClrScr();

    case x of
        62: begin
            GoToXY(47, 4);
            writeln('CASSE BRIQUE STPI EDITION');
            GoToXY(55, y);
            writeln('Niveau 1');
            GoToXY(55, y + 2);
            writeln('Niveau 2');
            GoToXY(55, y + 4);
            writeln('Niveau 3');
            GoToXY(63, 14);
        end;
        
        61: begin //affichage des règles
            DoneKeyBoard();
            assign(F2, 'Regles.txt');
            reset(F2);

            while not eof(F2) do
            begin
                readln(F2, S);
                writeln(S);
            end;

            RetourArriereMenu(X, Y, mur, T, C, f, f2, V, GraphicsDriver, GraphicsMode, ErrCode, s);
        end;
    end;        

    x := 63;

    repeat //boucle pour déplacer le curseur de ahut en bas dans la fenêtre de la séléction des niveau
        t := GetKeyEvent();
        t := TranslateKeyEvent(t);
        c := GetKeyEventChar(t);
    
        if c = 's' then
        begin
            if y < 16 then
            begin
                GoToXY(x, y + 2);
                y := y + 2;
            end;
        end;
    
        if c = 'z' then
        begin
            if y > 12 then
            begin
                GoToXY(x, y - 2);
                y := y - 2; 
            end;
        end;
    until (c = 'm') or (c = 'w');

    if c = 'm' then
    begin
        DoneKeyboard();
        case y of //pour chaque niveau séléctionné, une valeur est assignée à mur (ça serivira au déroulement des procédures ci-dessous)
            12: mur := 1;
            14: mur := 2;
            16: mur := 3;
        end;

        ClrScr();
    
        GraphicsDriver := Detect; //initialisation de l'unité graph
        InitGraph(GraphicsDriver, GraphicsMode,'C:\PP\BGI');
        ErrCode := GraphResult;
    
        If GraphResult <> grOK Then //affichage d'un message d'erreur si ça n'arrive pas à trouver le fichier graphique dans le répertoire indiqué ci-dessus
        Begin
            Writeln('Une erreur graphique s est produite: ', GraphErrorMsg(ErrCode));
            Writeln('Le fichier graphique (.BGI) n a pas ete trouve, donc veuillez changer le chemin dans InitGraph');
            Readln;
            Halt(1);
        End 
        Else
        begin
            remplissageDoc(mur,F); 
            MiseEnPlaceMur(mur,F,V);
        end;

        readln;
        closegraph;
    end;

    if c= 'w' then
        RetourArriereMenu(X,Y,mur,T,C,f,f2,V, GraphicsDriver, GraphicsMode, ErrCode,s);

end.

Here is the unit in which is stored all the procedures needed to run the main program

unit jeu;

interface

uses 
    sysutils, Crt, Keyboard, graph;

const 
    MAXtabX = 100;
    MAXtabY = 50;
      
    Type r = array [1..MAXtabX,1..MAXtabY] of Integer;
      
    procedure remplissageDoc(m: Integer; var f: Text); //remplir les documents aléatoirement à chaque lancement de niveau. m correspond au niveau que le joueur a choisi
    procedure MiseEnPlaceMur(m: Integer; var f: Text; res: r); //affichage du mur avec pour chaque bloque des vies (soit 1 soit 2 soit 3)
    procedure RetourArriereMenu(X,Y: Integer; var m: Integer; var T: TkeyEvent; var C: char; var f,f2: Text; var res: r; var GraphicsDriver, GraphicsMode, ErrCode : Smallint; s: String); //pour retourner en arrière dans n'importe quel endroit du menu
    procedure DessinerBrique(i,j: Integer; res: r; x1,y1,x2,y2: Integer); //dessine une brique

implementation

    procedure DessinerBrique(i, j : Integer; res : r; x1, y1, x2, y2 : Integer);
    begin
        writeln(x1, ',', y1, ' ', x2, ',', y2, '-', res[i][j]);
        setcolor(15);
        rectangle(x1, y1, x2, y2);

        if res[i][j]= 1 then
        begin
            setfillstyle(1,1);
            floodfill((x1+x2)div 2,(y1+y2)div 2,15); 
        end;
    
        if res[i][j] = 2 then
        begin
            setfillstyle(1, 2);
            floodfill((x1 + x2) div 2, (y1 + y2) div 2, 15); 
        end;
    
        if res[i][j]= 3 then
        begin
            setfillstyle(1,4);
            floodfill((x1 + x2) div 2, (y1 + y2) div 2, 15); 
        end;
    end;

    procedure remplissageDoc(m : Integer; var f : Text); 
    var 
        a : Integer;
    begin
        if m = 1 then 
        begin
            assign(f, 'Niveau 1.txt');
            rewrite(f);

            for a := 1 to 30 do //30 chiffres vont êtres saisis dans le fichier
            begin
                write(f, 1);
                writeln;
            end;
        
            close(f);
        end;
        
        if m = 2 then
        begin
            assign(f, 'Niveau 2.txt');
            rewrite(f);
            randomize();

            for a := 1 to 30 do
            begin
                write(f, random(2) + 1);
                writeln;
            end;

            close(f);
        end;    
    
        if m = 3 then
        begin
            assign(f, 'Niveau 3.txt');
            rewrite(f);
            randomize();

            for a := 1 to 30 do
            begin
                write(f, random(3) + 1);
                writeln;
            end;

            close(f);
        end;
    end;

    procedure MiseEnPlaceMur(m : Integer; var f : Text; res : r); 
    var 
        i, j : Integer;
        x1, y1, x2, y2 : Integer;
        s : String;
    begin
        i := 1;
        x1 := 200;
        x2 := 245;
        y1 := 0;
        y2 := 25;
        reset(f);
        read(f, s);

        while not eof do
        begin
            for j:= 1 to length(s) do 
            begin
                res[i][j] := StrToInt(s[j]); //remplissage du tableau des vies
                DessinerBrique(i, j, res, x1, y1, x2, y2);
                x1 := x2;
                x2 := x2 + 10;

                if (j = 5) or (j = 10) or (j = 15) or (j = 20) or (j = 25) then //pour avoir des 6 lignes de 5 briques 
                begin
                    x1 := 200;
                    x2 := 245;
                    y1 := y2;
                    y2 := y1 + 25
                end;
            end;
        end;

        i := i + 1; 
        close(f);
    end;

    procedure RetourArriereMenu(X, Y : Integer; var m : Integer; var T : TkeyEvent; var C : char; var f, f2 : Text; var res : r; var GraphicsDriver, GraphicsMode, ErrCode : Smallint; s : String); //retourner en arrière à n'importe quel moment dans le menu
    begin
        InitKeyBoard();
        T := GetKeyEvent();
        T := TranslateKeyEvent(T);
        C := GetKeyEventChar(T);

        if C = 'w' then
        begin
            X := 62;
            Y := 12;
            ClrScr();
            GoToXY(47, 4);
            writeln('CASSE BRIQUE STPI EDITION');
            GoToXY(55, Y);
            writeln('Niveaux');
            GoToXY(55, Y + 2);
            writeln('Regles');
            GoToXY(X,Y);

            repeat
                T := GetKeyEvent();
                T := TranslateKeyEvent(t);
                C := GetKeyEventChar(t);

                if C = 's' then
                begin
                    GoToXY(X - 1, Y + 2);
                    X := 61;
                end;

                if C = 'z' then
                begin
                    GoToXY(X, Y);
                    X := 62;
                end;
            until C = 'm';

            ClrScr();

            case X of
                62: begin
                    GoToXY(47, 4);
                    writeln('CASSE BRIQUE STPI EDITION');
                    GoToXY(55, Y);
                    writeln('Niveau 1');
                    GoToXY(55,Y + 2);
                    writeln('Niveau 2');
                    GoToXY(55,Y + 4);
                    writeln('Niveau 3');
                    GoToXY(63, 14);
                    x := 63;
                end;

                61: begin
                    DoneKeyBoard();
                    assign(F2, 'Regles.txt');
                    reset(F2);

                    while not eof(F2) do
                    begin
                        readln(F2, S);
                        writeln(S);
                    end;

                    RetourArriereMenu(X, Y, m, T, C, f, f2, res, GraphicsDriver, GraphicsMode, ErrCode, s);
                end;
            end;

            x:=63;

            repeat
                t := GetKeyEvent();
                t := TranslateKeyEvent(t);
                c := GetKeyEventChar(t);

                if c = 's' then
                begin
                    if y < 16 then
                    begin
                        GoToXY(x, y + 2);
                        y := y + 2;
                    end;
                end;

                if c = 'z' then
                begin
                    if y > 12 then
                    begin
                        GoToXY(x, y - 2);
                        y := y - 2;
                    end;
                end;
            until (c = 'm') or (c = 'w');

            if c = 'm' then
            begin
                DoneKeyboard();

                case y of
                    12: m := 1;
                    14: m := 2;
                    16: m := 3;
                end;

                ClrScr();
            
                GraphicsDriver := Detect; 
                InitGraph(GraphicsDriver, GraphicsMode, 'C:\PP\BGI');
                ErrCode := GraphResult;

                If GraphResult <> grOK Then 
                Begin
                    Writeln('Une erreur graphique s est produite: ', GraphErrorMsg(ErrCode));
                    Writeln('Le fichier graphique (.BGI) n a pas ete trouve, donc veuillez changer le chemin dans InitGraph');
                    Readln;
                    Halt(1);
                End 
                Else
                begin
                    remplissageDoc(m, f);
                    MiseEnPlaceMur(m, f, res);
                end; 

                readln;
                closegraph;
            end;

            if c = 'w' then
                RetourArriereMenu(X, Y, m, T, C, f, f2, res, GraphicsDriver, GraphicsMode, ErrCode, s);
        end;
    end;
end.
1 Answers

Graphics mode is failing to initialize but you are ignoring the result. Read GraphResult exactly once, and act on that.

Edit: put the BGI fonts in your .exe directory and use '' for the BGI path.

Code Organization

Your code is very disorganized and uses a lot of meaningless variable names — making it very hard to understand what you are trying to do. That and you keep trying to switch back and forth between graphics mode and text mode (and not quite getting it right).

This “answer” is designed to help you better organize your code. Since this is a graphical game, forget WriteLn and everything else that is not graphical. The very first thing you should do is initialize graphics mode. Put that in a procedure if you wish:

procedure Initialiser;
  var
    gd, gm : integer;
  begin
  gd := Detect;
  InitGraph( gd, gm, '' );
  if GraphResult <> grOK then
    begin
    WriteLn( 'Impossible de démarrer le mode graphique.' );
    Halt( 1 )
    end;
  ClearDevice
  end;

begin
Initialiser;
end.

Next you want to do a menu. Make that a function:

type
  ActionDeMenu = (Niveau1, Niveau2, Niveau3, Aider, Quitter);

function Menu : ActionDeMenu;
  begin
  // dessinez votre menu ici
  // obtenir l'entrée de l'utilisateur
  // retourner le choix de l'utilisateur
  end;

You can then update your main program. You might as well put it in a loop; Break to quit.

begin
Initialiser;
repeat
  case Menu of
    Niveau1: Jouer( 1 );
    Niveau2: Jouer( 2 );
    Niveau3: Jouer( 3 );
    Aider:   Aider;
    Quitter: Break
  end
until false;
CloseGraph
end.

After that you need to write procedures to show help and to play the game at a specified level of difficulty:

procedure Aider;
  begin
  // afficher l'aide
  // l'utilisateur doit appuyer sur Entrée (ou quelque chose) pour continuer
  end;

procedure Jouer( niveau : integer );
  begin
  // initialiser le niveau de jeu
  // jouer le jeu
  // affichage gagné/perdu
  end;

As you can see, we keep breaking tasks down into simpler tasks that:

  • do not need to be repeated
  • keep tasks separate
  • are simple

With just this organic sense of organization you can make the game much more understandable and easier to implement.

Related