Forum Programmation.c Graphisme retro en console

Posté par  . Licence CC By‑SA.
Étiquettes :
7
23
nov.
2025

Bonjour à tous,

J'ai découvert récemment qu'il est possible en C de positionner de façon simple le curseur n'importe où sur l'écran d'un terminal sans utiliser de bibliothèque dédiée telle que ncurses. Cela permet de faire des graphismes rétros du même style que ceux que l'on faisait autrefois en Basic avec des TRS-80 ou équivalent.

Vous connaissez sans doute déjà la méthode, mais je me permets de la poster ici au cas où cela aurait échappé à certains comme moi.

Voici par exemple comment tracer une sinusoïde :

#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <math.h>

int main(void)
    {
    struct winsize w;
    int x;
    double y;
    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0)
        {
        printf("\033[2J"); // Efface l'écran
        for (x=1;x<=w.ws_col;x++)
            {
            y=(sin((x-1)*4*3.1416/w.ws_col))*(w.ws_row-1)/2.5+(w.ws_row+1)/2.0;
            printf("\033[%.0f;%dH*",y,x); // Positionne le caractère "*" aux coordonnées x,y
            }       
        printf("\033[%d;%dH",0,0); // Positionne le curseur aux coordonnées 0,0
        }
    else
        {
        perror("Erreur");
        return 1;
        }
    return 0;
    }

Le résultat :

                             ***                                     ***
                           **   **                                 **   **
                          *       *                               *       *
                         *         *                             *         *
                        *           *                           *           *
                       *             *                         *             *

                      *               *                       *               *
                     *                 *                     *                 *
*                   *                                       *
                                        *
 *                 *                     *                 *
  *               *                       *               *

   *             *                         *             *
    *           *                           *           *
     *         *                             *         *
      *       *                               *       *
       **   **                                 **   **
         ***                                     ***

  • # Pas vraiment le C

    Posté par  (Mastodon) . Évalué à 8 (+5/-0). Dernière modification le 23 novembre 2025 à 17:04.

    La "magie" n'est pas dans le langage, mais dans le terminal qui va interpréter l'affichage (donc printf() dans le cas du C).

    Du coup tu peux le faire dans n'importe quel langage. Par exemple dans ton Bash tu peux taper:

    echo -e "\033[10;20HLinuxFr.org"

    et tu verras LinuxFr.org s'afficher sur la 10e ligne et à la 20e colonne.

    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

    • [^] # Re: Pas vraiment le C

      Posté par  . Évalué à 1 (+0/-0). Dernière modification le 23 novembre 2025 à 15:52.

      il y a aussi un printf dans les builtins du shell bash.

      Voir printf dans la page man du bash :

      man --pager='less -p "printf "' bash

      mais bon, pas dans la vielle (presque 20 ans de retard) version du bash qui est installée sur les mac.

      … et dans ce royaume, ceux qui y voient un peu plus clair sont parfois très mal vus.

      • [^] # Re: Pas vraiment le C

        Posté par  . Évalué à 3 (+1/-0). Dernière modification le 23 novembre 2025 à 22:16.

        effectivement tous les languages n'ont pas forcément accès à des manipulations de graphisme avancés (pixels, gui etc)

        En FORTH, on a la commande x y AT-XY pour afficher des caractères à un endroit donné de la console.

        Je me suis amusé a réaliser un petit programme similaire pour afficher une sinusoïde, cela fonctionne avec ueforth et gforth, ce sont les commentaires qui prennent le plus de place :

        : sinusoide 
        
        112 1 do   \ counter loop from 1 to 112
        i 
        dup        \ we duplicate the counter value to reuse it
        3 *        \ we scale a bit the value to display it better
        s>f        \ we convert the integer to real
        fsin       \ we calculate the sinus in radian
                   \ degree = radian x 180 / pi
        180e f* pi f/    \ we convert from radian to degree
        10e f*  f>s      \ we increase the precision and convert back to integer
        10 /             \ we move back the fixed point
        60 +             \ we shift the y axis 60 pixels below to fit the terminal
        5 /              \ we refine the displayed data
        \ . . cr         \ uncomment to display the calculated values (and comment the line below)
        at-xy 42 emit   \ emit a star * at the coordinates calculated above
        loop             
        ;
        
        page          \ clear the page
        sinusoide       
        0 80 at-xy     \ we put the prompt under the graph
        bye           \ exit

        et cela affichera

                  * *                    * *                  * *                    * *                  * *
                *     *                *                    *     *                *     *                    *
                                     *       *                      *            *                      *       *
              *         *                                 *                                *
                                   *           *                                                      *           *
            *             *                                           *        *
                                                 *      *                                    *      *
                                 *                                      *                                           *
          *                 *                                                *
                                                   *  *                                        *
                               *                                                                  *                   *
                              *                                           **                                           *
                                                    *                                            *
         *                   *                       *                                          *
                                *                                        *  *
                                                  *                                                *                 *
           *               *                           *                                      *
                                  *                                    *      *
                                                *        *                                           *             *
             *           *                                                      *           *
                                    *         *                      *                                 *         *
               *       *                                   *                      *       *
                 *                    *     *                *     *                    *                *     *
                   * *                  * *                    * *                  * *                    * *
        
        

        Rappel important : vos amis qui se sont retournés contre vous parce que la TV leur a dit de le faire : ils le feront encore.

        • [^] # Re: Pas vraiment le C

          Posté par  . Évalué à 2 (+0/-0).

          je ne sais pas trop pourquoi, mais un nombre sur deux inversait le sens du graphique, j'ai corrigé cela en rajoutant après la ligne un test pour voir si le nombre de la boucle (i) était pair ou impair

          180e f* pi f/    \ we convert from radian to degree
          i 2 mod 0 = if fnegate then 

          pour inverser le sens, et maintenant cela évite d'afficher la double sinusoïde :

                                          ****                                        ****
                                        **    *                                      *    **
                                       *       *                                   **       *
                                      *         *                                            *
                                     *           *                                *           *
                                                  *                              *
                                    *              *                            *              *
                                   *                                                            *
                                                    *                          *
                                  *                  *                        *                  *
                                 *                                                                *
                                                      *                      *                                           *
                                *                                           *                      *
           *                   *                       *                                                                *
                                                        *                  *                        *
            *                 *                                                                      *                 *
             *               *                           *                *                                           *
                                                          *              *                            *
              *             *                              *            *                              *             *
               *           *                                                                            *           *
                *         *                                 *          *                                 *         *
                 *       *                                   *        *                                   *       *
                  **    *                                     **    **                                     *    **
                    ****                                        ****                                        ****
          
          

          Rappel important : vos amis qui se sont retournés contre vous parce que la TV leur a dit de le faire : ils le feront encore.

      • [^] # Re: Pas vraiment le C

        Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

        Je viens de vérifier sur un mac

        $ bash --version
        GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin22)
        Copyright (C) 2007 Free Software Foundation, Inc.
        $ help printf
        printf: printf [-v var] format [arguments]
            printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
            is a character string which contains three types of objects: plain
            characters, which are simply copied to standard output, character escape
            sequences which are converted and copied to the standard output, and
            format specifications, each of which causes printing of the next successive
            argument.  In addition to the standard printf(1) formats, %b means to
            expand backslash escape sequences in the corresponding argument, and %q
            means to quote the argument in a way that can be reused as shell input.
            If the -v option is supplied, the output is placed into the value of the
            shell variable VAR rather than being sent to the standard output.

        Je pense que c’est la page de manuel qui n’est pas à jour (mais quand je fais un man bash et que dedans je fais un /printf je trouve bien, bizarre)

        “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: Pas vraiment le C

          Posté par  . Évalué à 2 (+1/-0).

          Bonjour

          Je pense que sur ton mac, la ligne de commande :

          help printf
          

          …a dû te retourner la page d'aide de l'exécutable /usr/bin/printf

          Sur mon système debian sur PC, il y a le printf du bash (<=> dans les builtins du bash)
          et il y a aussi l'exécutable /usr/bin/printf

          mic@deb12x:~$ which printf
          /usr/bin/printf
          mic@deb12x:~$ 
          
          mic@deb12x:~$ file /usr/bin/printf
          /usr/bin/printf: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=9fb0f8c276c2fb7d6fdd13ff28a01088f25440bb, for GNU/Linux 3.2.0, stripped
          mic@deb12x:~$

          … et dans ce royaume, ceux qui y voient un peu plus clair sont parfois très mal vus.

          • [^] # Re: Pas vraiment le C

            Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

            Tu as oublié que je précise à la fin que « quand je fais un man bash et que dedans je fais un /printf [↵] je trouve bien » 😉
            Et j’ai exprès évité de demander la page de manuel de la commande car je voulais précisément afficher l’aidé de la commande intégrée

            $ help help
            help: help [-s] [pattern ...]
                Display helpful information about builtin commands.  If PATTERN is
                specified, gives detailed help on all commands matching PATTERN,
                otherwise a list of the builtins is printed.  The -s option
                restricts the output for each builtin command matching PATTERN to
                a short usage synopsis.

            Il faut faire attention ici à la précision « information about builtin commands » ; et si tu fais help tout court (ou suivi d’un nom de commande externe) alors « otherwise a list of the builtins is printed ».

            “It is seldom that liberty of any kind is lost all at once.” ― David Hume

            • [^] # Re: Pas vraiment le C

              Posté par  (Mastodon) . Évalué à 3 (+0/-0).

              pour être certain…

              Afficher si printf est interne ou externe:

              type printf

              Forcer l'utilisation de la version interne :

              builtin printf

              En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

            • [^] # Re: Pas vraiment le C

              Posté par  . Évalué à 1 (+0/-0). Dernière modification le 27 novembre 2025 à 19:31.

              … et si tu fais help tout court (ou suivi d’un nom de commande externe) alors « otherwise a list of the builtins is printed ». …

              Effectivement, merci pour ces précisions à Gil Cot ✔ et à gUI.

              … et dans ce royaume, ceux qui y voient un peu plus clair sont parfois très mal vus.

    • [^] # Re: Pas vraiment le C

      Posté par  (site web personnel, Mastodon) . Évalué à 4 (+2/-0).

      Une version Fortran :

      program main
        implicit none
      
        integer   :: x
        real      :: y
        real      :: PI   = acos(-1.0)
        character :: ESC  = achar(27)  ! Caractère d'échappement
        integer   :: COLS = 40
      
        ! Efface l'écran
        write(*, "(A)") ESC//"[2J"
      
        do x = 1, COLS
            y = sin((x-1)*4*PI/COLS) * (COLS-1) / 2.5 + (COLS+1)/2.0
            ! Positionne le caractère "*" aux coordonnées x,y :
            write(*, '(a1, "[", i0, ";", i0, "H*")') ESC, nint(y), x
        end do
      
        write(*, "(A)", advance="no") ESC//"[0;0H" 
      end program main
                     *                   *
                    * *                 * *
      
                   *   *               *   *
      
      
                  *     *             *     *
      
      
      
      
                 *       *           *       *
      
      
      
                *
      *                   *         *
      
      
      
       *       *           *       *
      
      
      
      
        *     *             *     *
      
      
         *   *               *   *
      
          * *                 * *
           *                   *
    • [^] # Re: Pas vraiment le C

      Posté par  . Évalué à 3 (+1/-1). Dernière modification le 27 novembre 2025 à 13:47.

      et une version bash :)

      j'ai préféré utiliser tput qui a le mérite de rester plus lisible, que les horribles \033[ :D
      on donne la hauteur de la courbe (en 1er paramètre)

      par contre je n'ai pas trouvé comment fair sin en bash, je me suis reposé sur bc, on peut le faire avec awk, perl python…

      donc ma version

      #!/usr/bin/env bash
      
      export HEIGHT=$1
      
      tput clear
      for (( x=1 ; x < $COLUMNS ; x++))
      do
          y=$(bc -l <<< "scale=1;s( ($x-1) /( 3.1416)) * $HEIGHT / 2 + $HEIGHT / 2  " | cut -d'.' -f1 )
          tput cup ${y:-0} $x
          echo -n "*"
      done
      tput cup $(($HEIGHT +1)) 0

      et j'ai préféré avoir une oscillation continue plutôt que juste 2 oscillations
      mais il suffit de remplacer la ligne avec bc par

          y=$(bc -l <<< "scale=1;s( ($x-1) * 4 * 3.1416 / $COLUMNS) * $HEIGHT / 2 + $HEIGHT / 2  " | cut -d'.' -f1 )

      Il ne faut pas décorner les boeufs avant d'avoir semé le vent

  • # ncurses

    Posté par  . Évalué à -1 (+3/-5).

    Une vraie lib C pour jouer avec la console ncurses

    Un exemple : https://gist.github.com/reagent/9743630

    • [^] # Re: ncurses

      Posté par  (Mastodon) . Évalué à 7 (+4/-0).

      Le journal en parle:

      sans utiliser de bibliothèque dédiée telle que ncurses

      En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.