Bibliothèques Graphiques

Implémentation et utilisation des bibliothèques d'affichage dans ARCADE

Introduction aux bibliothèques graphiques

Les bibliothèques graphiques sont des composants essentiels du projet ARCADE. Elles permettent d'afficher les jeux avec différents rendus graphiques tout en maintenant une logique de jeu cohérente. L'architecture du projet permet de changer de bibliothèque graphique en temps réel, sans redémarrer l'application.

Chargement dynamique

Les bibliothèques graphiques sont chargées dynamiquement à l'exécution sous forme de bibliothèques partagées (.so).

Interface IDisplayModule

Toutes les bibliothèques graphiques doivent implémenter l'interface IDisplayModule. Cette interface définit les méthodes nécessaires pour initialiser, afficher et gérer les entrées utilisateur.

namespace arcade {
    class IDisplayModule {
    public:
        virtual ~IDisplayModule() = default;
        virtual void init() = 0;                // Initialise la bibliothèque graphique
        virtual void stop() = 0;                // Arrête la bibliothèque graphique
        virtual void clear() = 0;               // Efface l'écran
        virtual void render() = 0;              // Effectue le rendu
        virtual void present() = 0;             // Présente le rendu à l'écran
        virtual bool isKeyPressed(const std::string &key) = 0;  // Vérifie si une touche est pressée
        virtual std::string getName() const = 0; // Retourne le nom de la bibliothèque
        virtual void handleInput() = 0;         // Gère les entrées utilisateur
        virtual bool shouldQuit() const = 0;    // Vérifie si l'utilisateur veut quitter
        virtual void drawRect(int x, int y, int width, int height, int r, int g, int b, int a) = 0;  // Dessine un rectangle
        virtual void drawText(const std::string& text, int x, int y, int r, int g, int b, int a) = 0; // Affiche du texte
        virtual void drawCircle(int x, int y, int radius, int r, int g, int b, int a) = 0;  // Dessine un cercle
    };
}

Description des méthodes

init()

Initialise la bibliothèque graphique (création de fenêtre, chargement de ressources, etc.).

stop()

Arrête proprement la bibliothèque graphique (libération des ressources, fermeture de fenêtre).

clear()

Efface le contenu de l'écran pour préparer un nouveau rendu.

render()

Effectue le rendu des éléments graphiques.

present()

Présente le rendu à l'écran (équivalent à un swap buffer).

isKeyPressed(const std::string &key)

Vérifie si une touche spécifique est pressée. Les touches sont identifiées par des chaînes standardisées comme "UP", "DOWN", "ESCAPE", etc.

getName() const

Retourne le nom de la bibliothèque graphique pour l'affichage dans l'interface.

handleInput()

Gère les événements d'entrée utilisateur (clavier, souris).

shouldQuit() const

Indique si l'utilisateur a demandé à quitter l'application (par exemple en fermant la fenêtre).

drawRect(int x, int y, int width, int height, int r, int g, int b, int a)

Dessine un rectangle aux coordonnées (x,y) avec la largeur, hauteur et couleur RGBA spécifiées.

drawText(const std::string& text, int x, int y, int r, int g, int b, int a)

Affiche du texte aux coordonnées (x,y) avec la couleur RGBA spécifiée.

drawCircle(int x, int y, int radius, int r, int g, int b, int a)

Dessine un cercle aux coordonnées (x,y) avec le rayon et la couleur RGBA spécifiés.

virtual std::string getTextInput(const std::string& prompt, const std::string& initialText = "") = 0;

Permet de rentrer des caractères dans une chaine de charactères.

Exemple d'implémentation: SFML

Voici un exemple d'implémentation de l'interface IDisplayModule avec la bibliothèque SFML.

/*
** EPITECH PROJECT, 2025
** B-OOP-400-COT-4-1-arcade-james.gbetchedji
** File description:
** SFMLDisplay
*/

#ifndef SFMLDISPLAY_HPP_
#define SFMLDISPLAY_HPP_

#include "IDisplayModule.hpp"
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <map>

namespace arcade {
    class SFMLDisplay : public IDisplayModule {
    public:
        SFMLDisplay();
        ~SFMLDisplay() override;
        
        void init() override;
        void stop() override;
        void clear() override;
        void render() override;
        void present() override;
        bool isKeyPressed(const std::string &key) override;
        std::string getName() const override;
        void handleInput() override;
        bool shouldQuit() const override;
        void drawRect(int x, int y, int width, int height, int r, int g, int b, int a) override;
        void drawText(const std::string& text, int x, int y, int r, int g, int b, int a) override;
        void drawCircle(int x, int y, int radius, int r, int g, int b, int a) override;
        virtual void drawCircle(int x, int y, int radius, int r, int g, int b, int a) = 0;
        virtual std::string getTextInput(const std::string& prompt, const std::string& initialText = "") = 0;
        
    private:
        sf::RenderWindow* _window;
        sf::Font _font;
        std::map<std::string, sf::Keyboard::Key> _keyMap;
        bool _quit;
    };
}

#endif /* !SFMLDISPLAY_HPP_ */
/*
** EPITECH PROJECT, 2025
** B-OOP-400-COT-4-1-arcade-james.gbetchedji
** File description:
** SFMLDisplay
*/

#include "../includes/Display/SFMLDisplay.hpp"

using namespace arcade;

namespace arcade {

    SFMLDisplay::SFMLDisplay() : _window(nullptr), _quit(false) {
        _keyMap["UP"]     = sf::Keyboard::Up;
        _keyMap["DOWN"]   = sf::Keyboard::Down;
        _keyMap["LEFT"]   = sf::Keyboard::Left;
        _keyMap["RIGHT"]  = sf::Keyboard::Right;
        _keyMap["ESCAPE"] = sf::Keyboard::Escape;
        _keyMap["RETURN"] = sf::Keyboard::Enter;
        _keyMap["SPACE"]  = sf::Keyboard::Space;
        _keyMap["R"]      = sf::Keyboard::R;
        _keyMap["N"]      = sf::Keyboard::N;
        _keyMap["Q"]      = sf::Keyboard::Q;
        _keyMap["E"]      = sf::Keyboard::E;
        _keyMap["M"]      = sf::Keyboard::M;
        _keyMap["F5"]     = sf::Keyboard::F5;
        _keyMap["F6"]     = sf::Keyboard::F6;
        _keyMap["P"]      = sf::Keyboard::P;
        _keyMap["Y"]      = sf::Keyboard::Y;
    }

    // Autres méthodes de l'implémentation...
}
/*
** EPITECH PROJECT, 2025
** B-OOP-400-COT-4-1-arcade-james.gbetchedji [WSL: Ubuntu]
** File description:
** SFMLModule
*/

#include "../includes/Display/SFMLDisplay.hpp"

extern "C" {
    arcade::IDisplayModule *createDisplay()
    {
        return new arcade::SFMLDisplay();
    }
    
    void destroyDisplay(arcade::IDisplayModule *display)
    {
        delete display;
    }
}

Créer une nouvelle bibliothèque graphique

Voici les étapes à suivre pour créer une nouvelle bibliothèque graphique compatible avec ARCADE :

- Créer une classe qui implémente IDisplayModule

Créez une classe qui hérite de l'interface IDisplayModule et implémentez toutes ses méthodes virtuelles.

- Implémenter les fonctions d'exportation

Définissez les fonctions externes createDisplay et destroyDisplay qui seront utilisées par le chargeur de bibliothèques dynamiques.

extern "C" {
    arcade::IDisplayModule *createDisplay()
    {
        return new YourDisplayModule();
    }
    
    void destroyDisplay(arcade::IDisplayModule *display)
    {
        delete display;
    }
}

- Compiler la bibliothèque partagée

Compilez votre code en une bibliothèque partagée (.so) selon la convention de nommage arcade_<nom_lib>.so et placez-la dans le répertoire ./lib/.

g++ -shared -fPIC -o lib/arcade_mylib.so MyDisplay.cpp MyModule.cpp -lmygraphlib

Conseils d'implémentation

Gestion des touches

Utilisez une map pour faire correspondre les noms de touches standardisés aux constantes spécifiques de votre bibliothèque graphique.

Gestion des ressources

Assurez-vous de bien initialiser et libérer les ressources dans les méthodes init() et stop().

Compatibilité

N'oubliez pas que votre bibliothèque doit être interchangeable avec les autres. Assurez-vous que les coordonnées et dimensions sont cohérentes.

Tests

Testez votre bibliothèque avec différents jeux pour vous assurer de sa compatibilité et de son bon fonctionnement.

Bibliothèques graphiques supportées

ARCADE supporte actuellement les bibliothèques graphiques suivantes :

nCurses

Interface en mode texte pour terminal.

SDL2

Simple DirectMedia Layer, bibliothèque multimédia cross-platform.

SFML

Simple and Fast Multimedia Library, bibliothèque orientée objet pour le développement de jeux.

Votre bibliothèque ?

Suivez ce guide pour ajouter votre propre bibliothèque graphique au projet !