Programmation graphique en C avec SDL2

Se connecter pour s'inscrire

Présentation du cours

Création d’applications graphiques en C avec la bibliothèque SDL2.

  1. Public cible

    Débutants, étudiants et professionnels qui souhaitent acquérir une pratique structurée dans ce domaine.

  2. Objectifs

    Comprendre les notions essentielles et les appliquer dans un projet vérifiable.

  3. Prérequis

    Aucune connaissance préalable n’est strictement obligatoire ; les prérequis détaillés sont précisés dans les ateliers.

  4. Niveau

    Tous niveaux

  5. Ressources

    • Documentation officielle et références citées dans les ateliers.
    • Exercices, examens et projet de synthèse du catalogue.
  6. Validation des compétences

    La validation repose sur les évaluations actives et les livrables pratiques du cours.

  7. Besoins techniques

    Un ordinateur, un navigateur et les outils indiqués dans le premier atelier sont suffisants pour commencer.

Exercices, examens et projets

Programmation graphique SDL2

Exercice

Atelier de mise en pratique

Réaliser une activité pratique et documenter ses choix.

Obligatoire Consulter
Examen

Examen de fin de module

Évaluer les notions et leur mise en pratique.

Obligatoire Consulter
Projet

Projet de synthèse

Livrer un résultat complet, testé et documenté.

Livrables :

  • Production attendue
  • Documentation
  • Présentation
Obligatoire Consulter
  1. Syllabus

    1. Informations du cours

      1. Durée : 12 semaines
      2. Format : Cours magistral et travaux pratiques (3 heures par semaine)
      3. Prérequis : Connaissance de base en programmation C, ainsi qu'une compréhension de base des concepts mathématiques et algorithmiques.
      4. Public cible : Ce cours est destiné aux étudiants en informatique et aux passionnés de la programmation C qui souhaitent apprendre à créer des applications graphiques.
    2. Objectifs du cours

      1. Installer et configurer SDL2
      2. Comprendre les bases de la bibliothèque SDL
      3. Créer des fenêtres et gérer les événements
      4. Dessiner des formes primitives et des images
      5. Gérer des ressources telles que des images, des sons et des polices de caractères
      6. Développer des applications graphiques interactives en C
      7. Apprendre à gérer les événements utilisateur et les animations
      8. Créer des jeux simples et des simulations graphiques
      9. Développer des jeux vidéo simples avec SDL2
  2. Contenu du cours

    1. Introduction

      1. Présentation du cours et des objectifs
      2. Introduction à SDL

        Simple DirectMedia Layer (SDL) est une bibliothèque de développement multimédia multi-plateforme conçue pour fournir un accès de bas niveau au matériel multimédia tel que le son, le clavier, la souris, le joystick et les cartes graphiques. Elle offre des fonctionnalités pour la gestion des graphiques, de l'audio, des entrées et sorties, des threads, des timers et bien plus encore. SDL2 est largement utilisée pour créer des applications multimédias telles que des jeux vidéo, des lecteurs vidéo, des émulateurs et des visualisations graphiques.

        SDL2 est la deuxième version majeure de cette bibliothèque, apportant des améliorations et de nouvelles fonctionnalités par rapport à SDL1.

        SDL est prisée pour le développement de jeux et d'applications multimédia en raison de sa portabilité (Windows, macOS, Linux, iOS, Android, etc.) et de sa simplicité.

      3. Installation et configuration de SDL2

        1. Sous Linux (Ubuntu/Debian)

                            
                              sudo apt-get update
                              sudo apt-get install libsdl2-dev
                            
                          
        2. Sous macOS

                            
                              brew install sdl2
                            
                          
        3. Sous Windows

          Téléchargez les fichiers de développement depuis le site officiel de SDL (https://www.libsdl.org/) et configurez votre environnement de développement pour inclure les headers et les bibliothèques SDL.

      4. Concepts de base

        1. Initialisation et nettoyage de SDL

          Avant d'utiliser les fonctionnalités de SDL2 dans votre programme, il est nécessaire d'initialiser la bibliothèque. Cela implique de charger les modules nécessaires et de configurer l'environnement SDL2.

          1. Appeler `SDL_Init(SDL_INIT_VIDEO)` pour initialiser le sous-système vidéo de SDL2 et
          2. Vérifier les erreurs d'initialisation avec `SDL_GetError()`.
          3. Nettoyer ces sous-systèmes après utilisation avec `SDL_Quit`.
                      
                      #include <SDL2/SDL.h>
          
                      int main() 
                      {
                          // Initialiser SDL2
                          if (SDL_Init(SDL_INIT_VIDEO) != 0) 
                          {
                              printf("Erreur d'initialisation de SDL2 : %s\n", SDL_GetError());
                              return 1;
                          }
          
                          // Votre code ici
                          // Quitter SDL2
                          SDL_Quit();
                  
                          return 0;
                      }
                      
                    
          Dans cet exemple, SDL_Init() est appelé avec le flag SDL_INIT_VIDEO pour initialiser uniquement le sous-système vidéo de SDL2. Si vous avez besoin d'utiliser d'autres fonctionnalités, comme l'audio ou les événements, vous devez ajouter les flags correspondants à l'argument SDL_Init().
        2. Création et Gestion de Fenêtres

          Les fenêtres sont essentielles pour toute application graphique car elles fournissent une surface sur laquelle dessiner et interagir avec l'utilisateur.

          SDL permet de créer des fenêtres graphiques pour afficher du contenu.

          Pour afficher des graphiques, il faut créer une fenêtre avec `SDL_CreateWindow`.

          1. Déclaration d'une variable de type SDL_Window avec `SDL_Window*`.
          2. Création de la fenêtre avec SDL_CreateWindow`SDL_CreateWindow()`.
          3. Vérification de la réussite de la création de la fenêtre`SDL_GetError()`.
          1. Introduction à `SDL_Window*`

            `SDL_Window` est une structure définie dans SDL2 pour représenter une fenêtre. Elle est utilisée en conjonction avec d'autres fonctions de SDL pour manipuler les fenêtres.

            typedef struct SDL_Window SDL_Window;

            Un pointeur vers une structure SDL_Window est déclaré comme suit :

            SDL_Window* window;

            Ce pointeur permettra de manipuler dynamiquement la fenêtre créée pendant l'exécution du programme.

          2. Création d'une Fenêtre avec SDL_CreateWindow

            La fonction `SDL_CreateWindow` est utilisée pour créer une nouvelle fenêtre avec les paramètres spécifiés.

          3. Prototype de la fonction

            SDL_Window* SDL_CreateWindow(const char* title, int x, int y, int w, int h, Uint32 flags);
          4. Paramètres de SDL_CreateWindow

            1. title

              1. Type : const char*
              2. Description : Le titre de la fenêtre qui apparaîtra dans la barre de titre.
              3. Exemple : "Mon application SDL2"
            2. x

              1. Type : int
              2. Description : La position horizontale de la fenêtre sur l'écran.
              3. Spécial : Peut être SDL_WINDOWPOS_CENTERED pour centrer la fenêtre horizontalement ou SDL_WINDOWPOS_UNDEFINED pour laisser SDL choisir la position automatiquement.
            3. y

              1. Type : int
              2. Description : La position verticale de la fenêtre sur l'écran.
              3. Spécial : Peut être SDL_WINDOWPOS_CENTERED pour centrer la fenêtre verticalement ou SDL_WINDOWPOS_UNDEFINED pour laisser SDL choisir la position automatiquement.
            4. w

              1. Type : int
              2. Description : La largeur de la fenêtre en pixels.
              3. Exemple : 800
            5. h

              1. Type : int
              2. Description : La hauteur de la fenêtre en pixels.
              3. Exemple : 600
            6. flags

              1. Type : Uint32
              2. Description : Un masque de bits de zéro ou plusieurs drapeaux pour spécifier des options pour la fenêtre.
              3. Options courantes :
                1. SDL_WINDOW_SHOWN : Rendre la fenêtre visible dès sa création.
                2. SDL_WINDOW_HIDDEN : Créer la fenêtre sans l'afficher.
                3. SDL_WINDOW_FULLSCREEN : Créer la fenêtre en mode plein écran.
                4. SDL_WINDOW_RESIZABLE : Permettre à la fenêtre d'être redimensionnée par l'utilisateur.
                5. SDL_WINDOW_OPENGL : Créer une fenêtre compatible avec OpenGL.
            7. Retour de la Fonction

              1. Type : SDL_Window*
              2. Description : Retourne un pointeur vers une structure SDL_Window représentant la nouvelle fenêtre.
              3. En cas d'échec : Retourne NULL et la fonction SDL_GetError() peut être utilisée pour obtenir une chaîne de caractères décrivant l'erreur.
          5. Exemple de Création de Fenêtre

                                    
                                    #include <SDL2/SDL.h>
                                    #include <stdio.h>
            
                                    int main(int argc, char* argv[]) {
                                        // Initialiser SDL
                                        if (SDL_Init(SDL_INIT_VIDEO) != 0) {
                                            printf("Erreur d'initialisation de SDL: %s\n", SDL_GetError());
                                            return 1;
                                        }
            
                                        // Déclaration du pointeur de fenêtre
                                        SDL_Window* window;
            
                                        // Créer une fenêtre
                                        window = SDL_CreateWindow(
                                            "Mon application SDL2",       // Titre de la fenêtre
                                            SDL_WINDOWPOS_CENTERED,       // Positionnement horizontal centré
                                            SDL_WINDOWPOS_CENTERED,       // Positionnement vertical centré
                                            800,                          // Largeur de la fenêtre en pixels
                                            600,                          // Hauteur de la fenêtre en pixels
                                            SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE // Drapeaux : visible et redimensionnable
                                        );
            
                                        // Vérifier si la fenêtre a été créée avec succès
                                        if (window == NULL) {
                                            printf("Erreur de création de fenêtre : %s\n", SDL_GetError());
                                            SDL_Quit();
                                            return 1;
                                        }
            
                                        // Ajoutez ici votre boucle principale et logique de rendu
            
                                        // Détruire la fenêtre avant de quitter
                                        SDL_DestroyWindow(window);
                                        SDL_Quit();
            
                                        return 0;
                                    }
                                    
                                
            Cet exemple crée une fenêtre nommée "Mon application SDL2" centrée sur l'écran, avec une largeur de 800 pixels et une hauteur de 600 pixels. La fenêtre est également visible et redimensionnable.
          6. Conclusion

            La création et la gestion de fenêtres avec SDL sont des étapes essentielles dans le développement d'applications graphiques. Comprendre comment utiliser SDL_Window* et SDL_CreateWindow est fondamental pour construire des interfaces utilisateur interactives et visuellement attrayantes. Ce module vous a introduit aux bases de cette gestion, ouvrant la voie à des concepts plus avancés que nous aborderons dans les modules suivants.

        3. Gestion des événements

          SDL fournit un mécanisme pour gérer les événements utilisateur, tels que les clics de souris, les pressions de touches et les redimensionnements de fenêtre.

                     
                      SDL_Event event;
          
                      while (running) {
                      // Récupérer les événements
                      if (SDL_PollEvent(&event)) {
                          switch (event.type) {
                          case SDL_QUIT:
                              running = false;
                              break;
          
                          case SDL_KEYDOWN:
                              if (event.key.keysym.sym == SDLK_ESCAPE) {
                              running = false;
                              }
                              break;
          
                          // Gérer d'autres événements ici
                          }
                      }
          
                      // Mettre à jour et afficher le contenu de la fenêtre
                      }
                      
                    
          Dans cet exemple, une boucle while est utilisée pour récupérer les événements à l'aide de la fonction SDL_PollEvent(). Le type d'événement est ensuite analysé et traité en conséquence. Dans ce cas, les événements SDL_QUIT et `SDL_KEYDOWN
    2. Graphiques 2D

      1. Introduction

        Le module "Graphiques 2D" se concentre sur les concepts et techniques de base pour dessiner des formes primitives, gérer les couleurs, afficher des images et effectuer des transformations graphiques. SDL2 permet de créer des applications graphiques interactives en utilisant ces fonctionnalités. Dans ce module, nous allons explorer comment dessiner des points, des lignes, des rectangles, des cercles et des triangles, ainsi que la gestion des couleurs et des transformations graphiques

      2. Dessin de Formes Primitives

        Les formes primitives sont les éléments graphiques de base que vous pouvez dessiner à l'écran. SDL2 permet de dessiner des lignes, des rectangles et des points. Pour dessiner des cercles, nous devons implémenter notre propre fonction.

        1. Dessiner un Point

          Pour dessiner un point avec SDL2, vous utilisez la fonction SDL_RenderDrawPoint. Voici un exemple :

                    
                      SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // Blanc
                      SDL_RenderDrawPoint(renderer, 400, 300); // Dessine un point au centre de la fenêtre
                    
                  
        2. Lignes

          Pour dessiner une ligne, utilisez la fonction `SDL_RenderDrawLine`.

                
                SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // Rouge
                SDL_RenderDrawLine(renderer, 100, 100, 200, 200);
                
              
        3. Rectangles

          Pour dessiner des rectangles, vous pouvez utiliser SDL_RenderDrawRect pour les rectangles vides et SDL_RenderFillRect pour les rectangles pleins.

                    
                      SDL_Rect rect = {300, 100, 200, 150}; // x, y, width, height
          
                      SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); // Vert
                      SDL_RenderDrawRect(renderer, &rect);
          
                      SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); // Bleu
                      SDL_RenderFillRect(renderer, &rect);
                    
                  
          1. SDL_RenderDrawRect dessine un rectangle vert vide.
          2. SDL_RenderFillRect dessine un rectangle bleu plein.
        4. Triangle

          Pour dessiner un triangle, vous pouvez utiliser la fonction SDL_RenderDrawLine pour dessiner ses trois côtés :

                    
                      void SDL_DrawTriangle(SDL_Renderer *renderer, int x1, int y1, int x2, int y2, int x3, int y3) 
                      {
                          SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
                          SDL_RenderDrawLine(renderer, x2, y2, x3, y3);
                          SDL_RenderDrawLine(renderer, x3, y3, x1, y1);
                      }
          
                      // Utilisation
                      SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255); // Magenta
                      SDL_DrawTriangle(renderer, 400, 100, 500, 300, 300, 300); // Dessine un triangle.
                    
                  
        5. Dessin de Cercles

          SDL ne fournit pas de fonction pour dessiner des cercles, nous devons donc implémenter cette fonctionnalité nous-mêmes. Nous pouvons utiliser l'algorithme de tracé de cercle de Bresenham.

          1. l'algorithme de tracé de cercle de Bresenham

                                    
                                    void DrawCircle(SDL_Renderer* renderer, int centreX, int centreY, int radius) {
                                        int x = radius - 1;
                                        int y = 0;
                                        int tx = 1;
                                        int ty = 1;
                                        int err = tx - (radius << 1);
            
                                        while (x >= y) {
                                            // Chaque point est dessiné dans chaque octant
                                            SDL_RenderDrawPoint(renderer, centreX + x, centreY - y);
                                            SDL_RenderDrawPoint(renderer, centreX + x, centreY + y);
                                            SDL_RenderDrawPoint(renderer, centreX - x, centreY - y);
                                            SDL_RenderDrawPoint(renderer, centreX - x, centreY + y);
                                            SDL_RenderDrawPoint(renderer, centreX + y, centreY - x);
                                            SDL_RenderDrawPoint(renderer, centreX + y, centreY + x);
                                            SDL_RenderDrawPoint(renderer, centreX - y, centreY - x);
                                            SDL_RenderDrawPoint(renderer, centreX - y, centreY + x);
            
                                            if (err <= 0) {
                                                y++;
                                                err += ty;
                                                ty += 2;
                                            }
            
                                            if (err > 0) {
                                                x--;
                                                tx += 2;
                                                err += (tx - (radius << 1));
                                            }
                                        }
                                    }
                                    
                                
          2. Appeler fonction pour dessiner un cercle

            Nous pouvons maintenant appeler cette fonction pour dessiner un cercle :

                                        
                                        SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255); // Jaune
                                        DrawCircle(renderer, 400, 300, 100);
                                        
                                    
      3. Présentation du Rendu

        Une fois que toutes les formes sont dessinées, nous devons présenter le rendu à l'écran :

        SDL_RenderPresent(renderer);
        1. Rendu graphique

          Le rendu graphique, aussi appelé affichage graphique, est le processus de création d'une image visible à partir de données numériques. Il s'agit d'une étape essentielle dans la programmation graphique, car elle permet de transformer des informations abstraites en représentations visuelles que les utilisateurs peuvent percevoir et interagir avec.

        2. Les étapes

          Le rendu graphique implique plusieurs étapes:

          1. Transformation géométrique: Conversion des données 3D ou abstraites en coordonnées 2D adaptées à l'écran.
          2. Rasterisation: Conversion des primitives graphiques (lignes, triangles, polygones) en pixels.
          3. Application des textures: Ajout de détails visuels aux surfaces des objets 3D.
          4. Éclairage et ombrage: Simulation de l'éclairage pour donner du volume et de la profondeur à la scène.
          5. Post-traitement: Application d'effets visuels supplémentaires comme le flou, l'anti-aliasing et la correction des couleurs.

            L'anti-aliasing en programmation graphique

            L'anti-aliasing, aussi appelé lissage des bords ou anticrénelage, est une technique utilisée en infographie pour réduire l'effet d'escalier ou de crénelage visible sur les bords diagonaux ou incurvés des images numériques.

            1. Effet d'escalier

              L'effet d'escalier, ou crénelage, apparaît lorsque les pixels d'une image ne sont pas suffisamment nombreux pour représenter fidèlement les formes courbes ou diagonales. Cela se traduit par des bords irréguliers et saccadés, donnant à l'image un aspect pixellisé.

            2. Fonctionnement de l'anti-aliasing

              L'anti-aliasing vise à atténuer cet effet en augmentant le nombre de pixels utilisés pour représenter les bords. Il existe différentes méthodes pour y parvenir:

              1. Suréchantillonnage: Augmenter la résolution de l'image permet d'avoir plus de pixels disponibles pour représenter les détails des bords.
              2. Pondération des pixels: Attribuer des valeurs de couleurs intermédiaires aux pixels situés sur les bords, en fonction de leur proximité avec les pixels voisins.
              3. Filtrage des bords: Appliquer des algorithmes de filtrage pour adoucir les transitions de couleurs entre les pixels.
            3. Avantages de l'anti-aliasing

              L'anti-aliasing améliore la qualité visuelle des images en rendant les bords plus nets et plus fluides. Cela permet d'obtenir un rendu plus réaliste et esthétique, particulièrement important pour les images haute résolution et les jeux vidéo.

            4. Inconvénients de l'anti-aliasing

              L'anti-aliasing peut avoir un impact sur les performances, car il augmente le nombre de calculs nécessaires pour générer l'image. De plus, certaines méthodes d'anti-aliasing peuvent introduire une légère floue dans l'image.

            5. Utilisation de l'anti-aliasing

              L'anti-aliasing est généralement activé par défaut dans les logiciels de graphisme et les jeux vidéo. Le niveau d'anti-aliasing peut souvent être ajusté en fonction des préférences de l'utilisateur et des performances du système.

            6. Conclusion

              L'anti-aliasing est une technique importante en infographie pour améliorer la qualité visuelle des images en réduisant l'effet d'escalier sur les bords diagonaux ou incurvés. Il permet d'obtenir un rendu plus net, plus fluide et plus réaliste, particulièrement important pour les images haute résolution et les jeux vidéo.

        3. Les approches

          Le rendu graphique peut être réalisé par le biais de différents approches:

          1. Rendu logiciel: Le processeur CPU effectue tous les calculs nécessaires à la génération de l'image.
          2. Rendu matériel: Le GPU (processeur graphique) est utilisé pour accélérer le processus de rendu, offrant des performances et une qualité d'image supérieures.

        1. Renderer

          Un renderer, ou moteur de rendu, est un logiciel ou un composant matériel responsable de la création d'une image visible à partir de données graphiques. Il implémente les algorithmes et techniques nécessaires pour effectuer les étapes du rendu graphique décrites ci-dessus.

          En programmation graphique, un renderer est généralement utilisé en conjonction avec une API graphique (comme OpenGL ou DirectX) pour fournir une interface abstraite et simplifiée pour la création de scènes et la gestion du processus de rendu.

        2. Différents types de renderers

          1. Renderer immédiat: Génère l'image finale directement à partir des commandes graphiques reçues.
          2. Renderer différé: Stocke les commandes graphiques dans un tampon et les traite ensuite en une seule passe pour optimiser les performances.
          3. Renderer basé sur les tuiles: Divise l'écran en tuiles et rend chaque tuile indépendamment pour une meilleure gestion de la mémoire et des performances.

          Le choix du type de renderer dépend des besoins spécifiques de l'application et des ressources disponibles.

        En résumé

        1. Le rendu graphique est le processus de création d'une image visible à partir de données numériques.
        2. Un renderer est un logiciel ou un composant matériel qui implémente les algorithmes et techniques nécessaires pour effectuer le rendu graphique.
        3. Les renderers sont utilisés en conjonction avec des API graphiques pour fournir une interface abstraite et simplifiée pour la création de scènes et la gestion du processus de rendu.
      4. Boucle Principale et Nettoyage

        Enfin, nous ajoutons une boucle principale pour garder la fenêtre ouverte et gérer les événements. Nous nettoyons également les ressources avant de quitter.

                    
                    SDL_Event event;
                    int running = 1;
                    while (running) 
                    {
                        while (SDL_PollEvent(&event)) 
                        {
                            if (event.type == SDL_QUIT) 
                            {
                                running = 0;
                            }
                        }            }
        
                        SDL_DestroyRenderer(renderer);
                        SDL_DestroyWindow(window);
                        SDL_Quit();
        
                        return 0;
                    }
        
                    
                
      5. Code Complet

        Code complet pour dessiner des formes primitives avec SDL2

                
                #include <SDL2/SDL.h>
                #include <stdio.h>
        
                const int WINDOW_WIDTH = 800;
                const int WINDOW_HEIGHT = 600;
        
                void DrawCircle(SDL_Renderer* renderer, int centreX, int centreY, int radius) 
                {
                    int x = radius - 1;
                    int y = 0;
                    int tx = 1;
                    int ty = 1;
                    int err = tx - (radius << 1);
        
                    while (x >= y) 
                    {
                        SDL_RenderDrawPoint(renderer, centreX + x, centreY - y);
                        SDL_RenderDrawPoint(renderer, centreX + x, centreY + y);
                        SDL_RenderDrawPoint(renderer, centreX - x, centreY - y);
                        SDL_RenderDrawPoint(renderer, centreX - x, centreY + y);
                        SDL_RenderDrawPoint(renderer, centreX + y, centreY - x);
                        SDL_RenderDrawPoint(renderer, centreX + y, centreY + x);
                        SDL_RenderDrawPoint(renderer, centreX - y, centreY - x);
                        SDL_RenderDrawPoint(renderer, centreX - y, centreY + x);
        
                        if (err <= 0) 
                        {
                            y++;
                            err += ty;
                            ty += 2;
                        }
        
                        if (err > 0) 
                        {
                            x--;
                            tx += 2;
                            err += (tx - (radius << 1));
                        }
                    }
                }
        
                int main(int argc, char* argv[]) 
                {
                    if (SDL_Init(SDL_INIT_VIDEO) != 0) 
                    {
                        printf("Erreur d'initialisation de la SDL: %s\n", SDL_GetError());
                        return 1;
                    }
        
                    SDL_Window* window = SDL_CreateWindow("Dessin de formes primitives",
                                                           SDL_WINDOWPOS_CENTERED,
                                                           SDL_WINDOWPOS_CENTERED,
                                                            WINDOW_WIDTH, WINDOW_HEIGHT,
                                                            SDL_WINDOW_SHOWN);
                    if (!window) 
                    {
                        printf("Erreur de création de la fenêtre: %s\n", SDL_GetError());
                        SDL_Quit();
                        return 1;
                    }
        
                    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
                    if (!renderer) 
                    {
                        printf("Erreur de création du renderer: %s\n", SDL_GetError());
                        SDL_DestroyWindow(window);
                        SDL_Quit();
                        return 1;
                    }
        
                    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // Rouge
                    SDL_RenderDrawLine(renderer, 100, 100, 200, 200);
        
                    SDL_Rect rect = {300, 100, 200, 150}; // x, y, width, height
                    SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); // Vert
                    SDL_RenderDrawRect(renderer, &rect);
        
                    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); // Bleu
                    SDL_RenderFillRect(renderer, &rect);
        
                    SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255); // Jaune
                    DrawCircle(renderer, 400, 300, 100);
        
                    SDL_RenderPresent(renderer);
        
                    SDL_Event event;
                    int running = 1;
                    while (running) 
                    {
                        while (SDL_PollEvent(&event)) 
                        {
                            if (event.type == SDL_QUIT) 
                            {
                                running = 0;
                            }
                        }
                    }
        
                    SDL_DestroyRenderer(renderer);
                    SDL_DestroyWindow(window);
                    SDL_Quit();
        
                    return 0;
                }
        
                
              
      6. Gestion des couleurs et palettes de couleurs pour enrichir les visuels

        1. Introduction

          La gestion des couleurs et la création de palettes de couleurs harmonieuses sont des aspects essentiels pour créer des visuels attrayants et efficaces dans le domaine de la programmation graphique avec SDL2. Les couleurs ont un pouvoir puissant pour influencer les émotions, transmettre des messages et établir une identité visuelle cohérente.

        2. Représentation des couleurs en SDL2

          SDL2 utilise des structures de données spécifiques pour représenter les couleurs. La structure SDL_Color définit une couleur par ses composantes Rouge, Vert et Bleu (RVB) sur une échelle de 0 à 255. Vous pouvez également utiliser des formats de couleurs alternatifs comme RGBA (avec alpha pour la transparence) ou des valeurs hexadé decimales.

          SDL_Color red = {255, 0, 0}; // Rouge
          Représentation d'une couleur rouge en SDL2
        3. Prototypes de SDL_Color et SDL_SetRenderDrawColor en détail

          1. Structure SDL_Color

            La structure SDL_Color est utilisée pour représenter une couleur RVB (Rouge, Vert, Bleu) en SDL2. Elle est définie comme suit :

            1.                                                     
                                                                  typedef struct SDL_Color 
                                                                  {
                                                                      Uint8 r; /* Rouge (0-255) */
                                                                      Uint8 g; /* Vert (0-255) */
                                                                      Uint8 b; /* Bleu (0-255) */
                                                                      Uint8 a; /* Alpha (transparence, 0-255, facultatif) */
                                                                  } SDL_Color;
              
                                                                  
                                                              
              Uint8: Type de données défini dans les en-têtes SDL2 (SDL.h) pour représenter un entier non signé sur 8 bits. Cela signifie qu'il peut stocker des valeurs entières comprises entre 0 et 255 inclus.
              r: Composante Rouge (valeur de 0 à 255).
              g: Composante Vert (valeur de 0 à 255).
              b: Composante Bleu (valeur de 0 à 255).
              a: Composante Alpha (transparence, facultative, valeur de 0 à 255, 255 par défaut pour une couleur opaque).
            2.                                                     
                                                                  SDL_Color red = {255, 0, 0, 255}; // Rouge opaque
                                                                  
                                                              
              Exemple de création d'une couleur rouge opaque
            3.                                                     
                                                                  SDL_Color blue = {0, 0, 255, 128}; // Bleu semi-transparent (50% d'opacité)
                                                                  
                                                              
              Exemple de création d'une couleur bleue semi-transparente

            Uint8

            `Uint8` est un type de données défini dans les en-têtes SDL2 (SDL.h) pour représenter un entier non signé sur 8 bits. Cela signifie qu'il peut stocker des valeurs entières comprises entre 0 et 255 inclus.

            Le type Uint8 est utilisé dans divers contextes dans SDL2, notamment :

            • Représentation des couleurs : Les composantes Rouge, Vert et Bleu (RVB) d'une couleur sont généralement stockées en tant que valeurs Uint8 dans une structure SDL_Color.
            • Gestion des textures : Les données de pixels dans les textures SDL2 sont souvent stockées en tant que valeurs Uint8 représentant les composantes de couleur RVB ou alpha.
            • Masques d'événements : Les masques d'événements SDL2 utilisent des valeurs Uint8 pour indiquer les événements spécifiques qui se sont produits.
            • Gestion des touches du clavier : L'état des touches du clavier est parfois représenté par des valeurs Uint8 indiquant si une touche est pressée ou non.
            1. Avantages de Uint8

              1. Efficacité mémoire : Le type Uint8 ne consomme que 1 octet de mémoire par valeur, ce qui le rend efficace pour stocker des données compactes.
              2. Performances : Les opérations sur des valeurs Uint8 sont généralement rapides et optimisées par le processeur.
              3. Compatibilité : Le type Uint8 est compatible avec la plupart des langages de programmation et des architectures.
            2. Exemples d'utilisation de Uint8

              1.                                         
                                                        SDL_Color red = {255, 0, 0, 255}; // Rouge opaque (Uint8 pour R, G et B)
                                                        
                                                    
                Définir une couleur rouge opaque
              2.                                         
                                                        Uint8 key_state = SDL_GetKeyboardState(NULL);
                                                        if (key_state[SDL_SCANCODE_SPACE] & 1) 
                                                        {
                                                            // La touche espace est pressée
                                                        }
                                                        
                                                    
                Vérifier si une touche est pressée

              Remarques:

              1. Le type Uint8 est généralement utilisé pour stocker des données non négatives (0 à 255). Si vous avez besoin de stocker des valeurs entières négatives, vous pouvez utiliser des types de données comme Sint8 ou int.
              2. Pour des nombres entiers plus grands, vous pouvez utiliser des types de données comme Uint16 (16 bits), Uint32 (32 bits) ou Uint64 (64 bits).
          2. SDL_SetRenderDrawColor

            Fonction SDL_SetRenderDrawColor La fonction `SDL_SetRenderDrawColor` définit la couleur de dessin actuelle pour un SDL_Renderer. Cette couleur sera utilisée pour les opérations de dessin ultérieures, telles que le remplissage de formes ou le tracé de lignes, jusqu'à ce qu'une autre couleur soit définie.

            1.                                                     
                                                                  void SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
                                                                  
                                                              
              Prototype de la fonction
              renderer : Pointeur vers le SDL_Renderer pour lequel la couleur de dessin doit être définie.
              r : Valeur de la composante Rouge (0-255).
              g : Valeur de la composante Vert (0-255).
              b : Valeur de la composante Bleu (0-255).
              a : Valeur de la composante Alpha (transparence, 0-255, 255 par défaut pour une couleur opaque).
            2.                                                     
                                                                      SDL_Renderer *renderer = SDL_GetRenderer(window);
                                                                      SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // Rouge opaque
                                                                      int radius = 50;
                                                                      int x = 320;
                                                                      int y = 240;
                                                                      SDL_RenderFillCircle(renderer, x, y, radius); // Dessine un cercle rouge
                                                                  
                                                              
              Exemple d'utilisation pour dessiner un cercle rouge
            Remarques:
            La fonction SDL_SetRenderDrawColor ne modifie pas la couleur de pixels existants dans un rendu. Elle définit uniquement la couleur de dessin pour les opérations de dessin ultérieures. Pour modifier la couleur d'un pixel existant, vous devez utiliser des fonctions de dessin comme SDL_SetPixel ou SDL_FillRect en spécifiant la position et la couleur du pixel.
        4. Chargement et création de palettes de couleurs

          Vous pouvez charger des palettes de couleurs prédéfinies à partir de fichiers ou créer vos propres palettes en définissant manuellement les valeurs RVB ou en utilisant des outils de sélection de couleurs. SDL2 fournit des fonctions pour charger des images au format BMP, PNG et d'autres formats courants, qui peuvent contenir des palettes de couleurs intégrées.

                                      
                                      SDL_Surface* palette_image = SDL_image_Load("palette.bmp");
                                      if (palette_image) 
                                      {
                                          // Extraire la palette de couleurs de l'image
                                          SDL_Palette* palette = SDL_GetSurfacePalette(palette_image);
                                          if (palette) 
                                          {
                                              // Utiliser la palette de couleurs pour dessiner des éléments
                                          }
                                          SDL_FreePalette(palette);
                                          SDL_FreeSurface(palette_image);
                                      }
                                      
                                  
          Chargement d'une palette de couleurs à partir d'une image BMP
        5. Définition des couleurs d'arrière-plan et de remplissage

          SDL2 offre des fonctions pour définir les couleurs d'arrière-plan et de remplissage pour les surfaces de rendu. Cela permet de définir la couleur de base d'une zone avant d'y dessiner des éléments graphiques.

                                      
                                      SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); // Bleu
                                      SDL_RenderFillRect(renderer, NULL); // Remplit l'écran de bleu
                                      
                                  
      7. Affichage d'images et de textures

        L'affichage d'images et de textures est un élément essentiel de la programmation graphique avec SDL2. Cela permet d'enrichir vos visuels et de créer des interfaces utilisateur attrayantes.

        1. Chargement d'images

          SDL offre des fonctions pour charger des images à partir de différents formats de fichiers courants, tels que BMP, PNG, JPEG et GIF. La bibliothèque SDL_image est généralement utilisée pour cette tâche.

          1. Étapes de base pour charger une image

            1. Inclure l'en-tête SDL_image

              #include <SDL_image.h>
            2. Initialiser SDL_image

              if (!SDL_InitSubSystem(SDL_INIT_IMAGE)) {// Erreur d'initialisation de SDL_image}
            3. Charger l'image

                                                                              
                                                                              SDL_Surface* image = SDL_image_Load("image.png");
                                                                              if (!image) {
                                                                              // Erreur de chargement de l'image
                                                                              SDL_QuitSubSystem(SDL_INIT_IMAGE);
                                                                              SDL_Quit();
                                                                              return 1;
                                                                              }
                                                                              
                                                                          
            4. Utiliser l'image chargée (par exemple, pour la dessiner)

                                                                              
                                                                              // ...
                                                                              SDL_FreeSurface(image); // Libérer l'image après utilisation
                                                                              SDL_QuitSubSystem(SDL_INIT_IMAGE);
                                                                              
                                                                          
            5. Remarques

              1. Assurez-vous que le fichier image est accessible au programme et que le format est pris en charge par SDL_image.
              2. Vous pouvez utiliser des fonctions comme SDL_ImageGetRGBColorMap et SDL_SetColorKey pour manipuler les palettes de couleurs et la transparence des images.
              3. SDL_image fournit des options avancées pour le chargement d'images, telles que le redimensionnement, la rotation et la conversion de formats.
        2. Création de textures à partir d'images

          Pour afficher des images dans un contexte graphique accéléré par le GPU, il est nécessaire de créer des textures à partir des images chargées.

          Étapes pour créer une texture à partir d'une image :

          1. Créer un SDL_Renderer

                                                        
                                                        SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
                                                        if (!renderer) {
                                                        // Erreur de création du renderer
                                                        }
                                                        
                                                    
          2. Créer une texture à partir de l'image

                                                    
                                                    SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, image);
                                                    if (!texture) {
                                                    // Erreur de création de texture
                                                    SDL_DestroyRenderer(renderer);
                                                    SDL_FreeSurface(image);
                                                    SDL_QuitSubSystem(SDL_INIT_IMAGE);
                                                    SDL_Quit();
                                                    return 1;
                                                    }
                                                    
                                                
          3. Utiliser la texture pour le rendu

                                                        
                                                        SDL_RenderCopy(renderer, texture, NULL, NULL); // Copie la texture sur la surface de rendu
                                                        
                                                    
          4. Détruire la texture et l'image après utilisation

                                                        
                                                        SDL_DestroyTexture(texture);
                                                        SDL_FreeSurface(image);
                                                        
                                                    

            Remarques

            • Les textures sont des ressources GPU et doivent être gérées efficacement pour éviter les fuites de mémoire.
            • Vous pouvez utiliser des fonctions comme SDL_SetTextureBlendMode et SDL_SetTextureAlphaMod pour contrôler le mode de fusion et l'opacité des textures.
            • Les textures peuvent être créées à partir de surfaces générées par logiciel ou directement à partir de données brutes.
        3. Affichage de textures

          Pour afficher une texture à l'écran, vous devez la copier sur la surface de rendu du SDL_Renderer.

                                          
                                          void SDL_RenderCopy(SDL_Renderer* renderer, SDL_Texture* texture,
                                          const SDL_Rect* srcrect, const SDL_Rect* dstrect);
                                          /*
                                              renderer : Pointeur vers le SDL_Renderer sur lequel la texture doit être copiée.
                                              texture : Pointeur vers la texture à copier.
                                              srcrect : Rectangle source dans la texture (optionnel, utilise toute la texture par défaut).
                                              dstrect : Rectangle de destination sur la surface de rendu (optionnel, copie la texture à sa position d'origine par défaut).
                                          */
                                          
                                      
          Fonction SDL_RenderCopy
                                          
                                          SDL_RenderCopy(renderer, texture, NULL,
                                          
                                      
          Exemple d'affichage d'une texture entière à l'écran
        4. Surfaces et textures dans SDL2 : Définitions et distinctions

          1. Surfaces

            En programmation graphique avec SDL2, une surface est une structure de données qui représente une zone d'image bitmap. Elle stocke les pixels de l'image, leurs couleurs et d'autres informations associées. Les surfaces sont généralement créées à partir de fichiers d'image ou générées par programme.

            1. Caractéristiques des surfaces

              1. Stockage en mémoire CPU : Les pixels d'une surface sont stockés dans la mémoire CPU, ce qui peut limiter les performances graphiques.
              2. Gestion logicielle : Le rendu des surfaces est géré par le processeur CPU, ce qui peut être moins performant que le rendu GPU.
              3. Formats de pixels variés : Les surfaces peuvent stocker des images dans différents formats de pixels, tels que RGB, RGBA, BGRA, etc.
              4. Manipulation flexible : Vous pouvez manipuler les pixels d'une surface directement, appliquer des effets, créer des masques, etc.
            2. Utilisations des surfaces

              1. Chargement d'images : Les surfaces sont souvent utilisées pour charger des images à partir de fichiers.
              2. Dessin 2D simple : Vous pouvez dessiner des formes, des lignes et du texte directement sur une surface.
              3. Création de textures : Les surfaces peuvent servir de base pour la création de textures GPU.
              4. Manipulation d'images : Vous pouvez appliquer des transformations, des filtres et des effets aux surfaces.
          2. Textures

            Une texture est une ressource graphique stockée dans la mémoire GPU (carte graphique) et optimisée pour un rendu rapide. Elle représente une image ou un motif qui peut être appliquée à des objets 3D ou des surfaces 2D.

            1. Caractéristiques des textures

              1. Stockage en mémoire GPU : Les textures sont stockées dans la mémoire de la carte graphique, ce qui offre des performances de rendu supérieures.
              2. Rendu accéléré par le GPU : Le rendu des textures est géré par le GPU, ce qui permet des performances graphiques plus rapides.
              3. Formats de pixels optimisés : Les textures utilisent des formats de pixels optimisés pour le rendu GPU.
              4. Efficacité de la mémoire : Les textures permettent une utilisation plus efficace de la mémoire GPU que les surfaces.
            2. Utilisations des textures

              1. Rendu 3D : Les textures sont essentielles pour le rendu de surfaces et d'objets 3D.
              2. Effets visuels : Vous pouvez utiliser des textures pour appliquer des effets visuels, tels que des motifs, des lumières et des ombres.
              3. Animations : Les textures peuvent être animées pour créer des effets dynamiques.
              4. Optimisation des performances : L'utilisation de textures peut améliorer considérablement les performances graphiques.
          3. Conclusion

            • Les surfaces sont des structures de données flexibles pour stocker et manipuler des images en mémoire CPU.
            • Les textures sont des ressources graphiques optimisées pour un rendu rapide en mémoire GPU.
            • Les textures offrent de meilleures performances et une meilleure efficacité de la mémoire pour les applications graphiques exigeantes.

            Choisir entre une surface et une texture

            • Si vous avez besoin d'une manipulation flexible des pixels d'une image ou d'un dessin 2D simple, utilisez une surface.
            • Si vous avez besoin de performances graphiques rapides pour le rendu 3D, des effets visuels ou des animations, utilisez une texture.
      8. Transformations graphiques (rotations, translations, mises à l'échelle)
    3. Gestion des ressources

      1. Organisation des ressources

        Organisation des ressources pour un code propre et maintenable

        L'organisation efficace des ressources est un aspect crucial du développement de code propre et maintenable. Une structure claire et logique facilite la compréhension, la modification et la mise à jour du code, ce qui est essentiel pour la pérennité du projet et la collaboration entre les développeurs.



        Quelques principes clés pour organiser les ressources dans un projet de programmation graphique:
        1. Hiérarchie des dossiers clairs

          Adoptez une structure de dossiers hiérarchique qui reflète le type de média et son utilisation dans le projet. Par exemple, créez des dossiers principaux pour les images, les sons, les vidéos et les modèles 3D. Ensuite, créez des sous-dossiers pour catégoriser davantage les ressources en fonction de leur thème, de leur fonction ou de leur style.

          Exemple de structure de dossiers

                                          
                                          assets
                                          ├── images
                                          │   ├── backgrounds
                                          │   │   ├── menu.png
                                          │   │   └── jeu.jpg
                                          │   ├── personnages
                                          │   │   ├── joueur1.png
                                          │   │   └── joueur2.png
                                          │   └── objets
                                          │       ├── objet1.png
                                          │       └── objet2.png
                                          ├── sounds
                                          │   ├── effets
                                          │   │   ├── son_explosion.mp3
                                          │   │   └── son_saut.wav
                                          │   ├── musiques
                                          │       ├── musique_menu.ogg
                                          │       └── musique_jeu.mp3
                                          └── 3d_models
                                              ├── personnages
                                              │   ├── joueur1.fbx
                                              │   └── joueur2.obj
                                              └── objets
                                                  ├── objet1.gltf
                                                  └── objet2.3ds
                                          
                                      
        2. Noms de fichiers descriptifs

          Utilisez des noms de fichiers clairs et descriptifs qui indiquent le contenu du fichier. Évitez les noms génériques ou énigmatiques. Utilisez des mots-clés pertinents et des séparateurs clairs pour faciliter la recherche et l'identification des fichiers.

          Exemple de noms de fichiers

          1. `menu_background.jpg`
          2. `player1_jump.wav`
          3. `object3_high_poly.obj`
        3. Organisation par thème ou fonction

          Classez les ressources en fonction de leur thème ou de leur fonction dans le projet. Cela permet de regrouper les éléments liés et de faciliter leur recherche et leur utilisation. Par exemple, regroupez les images d'arrière-plan dans un dossier dédié, les sons d'effets dans un autre, et ainsi de suite.

        4. Utilisation de préfixes et de suffixes

          Utilisez des préfixes et des suffixes cohérents pour indiquer le type de média, la version ou l'état du fichier. Cela permet de différencier facilement les fichiers similaires et de maintenir une organisation claire.

          Exemple de préfixes et de suffixes

          1. `menu_ pour les images du menu`
          2. `sound_ pour les fichiers audio`
          3. `low_poly_ pour les modèles 3D basse résolution`
          4. `v2_ pour les versions mises à jour des fichiers`
        5. Gestion des versions et des sauvegardes

          Implémentez un système de contrôle de version comme Git pour suivre les modifications des fichiers de ressources, collaborer efficacement et revenir aux versions précédentes en cas de problème. Mettez en place des sauvegardes régulières pour protéger vos ressources précieuses contre les pertes accidentelles.

        6. Optimisation des ressources

          Optimisez les ressources en fonction de leur utilisation pour réduire la taille des fichiers et améliorer les performances. Utilisez des formats de compression appropriés, redimensionnez les images si nécessaire et supprimez les éléments redondants ou inutilisés.

        7. Documentation des ressources

          Documentez les ressources, y compris leur nom, leur description, leur format et leur utilisation prévue. Cela facilite la compréhension du projet par d'autres développeurs et la recherche rapide des ressources appropriées.

        8. Outils d'organisation des ressources

          Envisagez d'utiliser des outils d'organisation de ressources comme des gestionnaires de médias numériques ou des plugins spécifiques à votre environnement de développement. Ces outils peuvent automatiser des tâches telles que le renommage, la compression et la documentation des fichiers.

        Conclusion

        En suivant ces principes et en adaptant votre approche aux besoins spécifiques de votre projet, vous pouvez organiser efficacement les ressources graphiques, maintenir un code propre et améliorer la productivité du développement.

      2. Affichage d'images

        1. Chargement et gestion d'images
        2. Affichage d'images chargées
        3. Utilisation de textures SDL
        4. Blitting et rendu des textures sur l'écran
      3. Audio

        1. Chargement et gestion de sons
        2. Introduction à SDL_mixer pour la gestion audio
        3. Lecture et lecture de sons
        4. Mixage de sons
        5. Création d'effets sonores
      4. Polices de caractères

        1. Chargement et gestion de polices de caractères
    4. Animation

      1. Introduction à l'animation et aux techniques d'animation en programmation graphique
      2. Création d'animations simples en utilisant des boucles et des timers
      3. Gestion du temps et de la vitesse d'animation pour des mouvements fluides
    5. Gestion avancée des événements

      1. Événements multiples et gestion des états
      2. Introduction aux événements de fenêtre (redimensionnement, focus)
      3. Utilisation des timers SDL
    6. Gestion des collisions

      1. Détection des collisions entre objets
      2. Réactions aux collisions (rebonds, arrêt, etc.)
      3. Utilisation de bounding boxes et de cercles de collision
    7. Développement de jeux vidéo

      1. Introduction aux concepts de base du développement de jeux vidéo : game design, sprites, niveaux
      2. Création d'un jeu simple avec SDL2 en appliquant les principes de base
      3. Gestion des sprites et des animations pour les personnages et les éléments du jeu
      4. Mise en place des collisions et des interactions entre les éléments du jeu
    8. Optimisation et débogage

      1. Optimisation des performances graphiques
      2. Techniques de débogage pour les applications SDL
      3. Gestion de la mémoire et des ressources
  3. Projets et Évaluation

    1. Projets de fin de cours

      1. Présentation des projets de fin de cours
      2. Travail en groupe ou individuel sur un projet de choix
      3. Intégration des connaissances acquises
      4. Support et suivi des projets
    2. Présentation des projets et révision finale

      1. Présentation des projets par les étudiants
      2. Feedback et évaluation des projets
      3. Révision des concepts clés du cours
      4. Questions et réponses, et clôture du cours
    3. Évaluation

      1. Participation en classe et aux travaux pratiques : 20%
      2. Devoirs et petits projets : 40%
      3. Projet final : 40%

Publié le 09/05/2025