GraphicalDisplay.cpp h - JulianKerignard/ProjetJeuDeLaVie_POO GitHub Wiki

Fichier GraphicalDisplay.h

#ifndef GRAPHICALDISPLAY_H
#define GRAPHICALDISPLAY_H

#include <SFML/Graphics.hpp>
#include "Grid.h"
#include "Cell.h"
#include "DisplayManager.h"

class GraphicalDisplay : public DisplayManager {
public:
    // Constructeur avec initialisation des composants
    GraphicalDisplay(int windowWidth = 800, int windowHeight = 600);

    // Initialisation de l'affichage graphique
    void initialize() override;

    // Mise à jour de l'affichage graphique
    void update(const Grid& grid) override;

    // Gestion des événements utilisateur
    void handleEvents();

    // Fermeture de la fenêtre graphique
    void close() override;

    // Vérifie si la fenêtre est ouverte
    bool isWindowOpen() const;

    // Définir la grille à afficher
    void setGrid(Grid* grid) { this->grid = grid; }

    // Obtenir la vitesse d'itération actuelle
    float getIterationSpeed() const { return iterationSpeed; }

    // Définir la vitesse d'itération
    void setIterationSpeed(float speed) { iterationSpeed = speed; }

    // Mettre en pause ou reprendre le jeu
    void togglePause() { paused = !paused; }

    // Vérifie si le jeu est en pause
    bool isPaused() const { return paused; }

    // Définir le nombre d'itérations maximum
    void setMaxIterations(int maxIterations) { this->maxIterations = maxIterations; }

    // Définir le compteur d'itérations actuel
    void setIterationCount(int currentIteration) { this->currentIteration = currentIteration; }

private:
    sf::RenderWindow window;  // Fenêtre de rendu SFML
    sf::RenderTexture buffer;  // Texture de rendu pour le double buffering
    sf::RectangleShape cellShape;  // Forme rectangulaire pour dessiner les cellules
    sf::Font font;  // Police pour le texte
    sf::Text helpText;  // Texte d'aide
    sf::Text fpsText;  // Texte pour l'affichage des FPS
    sf::Clock fpsClock;  // Horloge pour calculer les FPS
    float cellSize;  // Taille des cellules
    bool isDrawing;  // Indique si le dessin est en cours
    Grid* grid;  // Pointeur vers la grille à afficher
    float lastFPS;  // Dernière valeur des FPS
    float iterationSpeed;  // Vitesse d'itération en millisecondes
    bool paused;  // Indique si le jeu est en pause
    int currentIteration;  // Compteur d'itérations actuel
    int maxIterations;  // Nombre maximum d'itérations

    // Vérifie si une cellule est visible dans la fenêtre
    bool isCellVisible(float x, float y, float windowWidth, float windowHeight) const;

    // Dessine une cellule à une position spécifiée
    void drawCell(float x, float y, float size, sf::Color color, bool drawOutline = false);

    // Met à jour l'affichage des FPS
    void updateFPS();

    // Dessine l'interface utilisateur
    void drawInterface(const Grid& grid);
};

#endif  // GRAPHICALDISPLAY_H

Fichier GraphicalDisplay.cpp

Implémentation de la Classe GraphicalDisplay

Constructeur

  • GraphicalDisplay(int windowWidth, int windowHeight) :
    • Initialise les composants de la fenêtre SFML, configure les paramètres de la fenêtre, et charge la police utilisée pour afficher le texte.
GraphicalDisplay::GraphicalDisplay(int windowWidth, int windowHeight)
    : window(sf::VideoMode(windowWidth, windowHeight), "Game of Life"),
      cellSize(10.0f),
      isDrawing(false),
      grid(nullptr),
      lastFPS(0.0f),
      iterationSpeed(100.0f),
      paused(false),
      currentIteration(0),
      maxIterations(0) {

    window.setVerticalSyncEnabled(true);
    window.setFramerateLimit(60);

    buffer.create(windowWidth, windowHeight);
    cellShape.setSize(sf::Vector2f(cellSize - 1, cellSize - 1));

    if (!font.loadFromFile("arial.ttf")) {
        std::cout << "Erreur de chargement de la police" << std::endl;
    }

    helpText.setFont(font);
    helpText.setCharacterSize(14);
    helpText.setFillColor(sf::Color::White);
    helpText.setPosition(10, 10);

    fpsText.setFont(font);
    fpsText.setCharacterSize(14);
    fpsText.setFillColor(sf::Color::Yellow);
    fpsText.setPosition(10, window.getSize().y - 20);
}

Méthodes

  • void initialize() :
    • Affiche un message d'initialisation et la vitesse initiale d'itération.
void GraphicalDisplay::initialize() {
    std::cout << "Initialisation de l'affichage graphique" << std::endl;
    std::cout << "Vitesse initiale : " << iterationSpeed << "ms" << std::endl;
}
  • bool isCellVisible(float x, float y, float windowWidth, float windowHeight) const :
    • Vérifie si une cellule est visible dans la fenêtre graphique en fonction de ses coordonnées.
bool GraphicalDisplay::isCellVisible(float x, float y, float windowWidth, float windowHeight) const {
    return x >= -cellSize && x <= windowWidth && y >= -cellSize && y <= windowHeight;
}
  • void drawCell(float x, float y, float size, sf::Color color, bool drawOutline) :
    • Dessine une cellule à une position spécifiée avec une certaine taille et couleur.
void GraphicalDisplay::drawCell(float x, float y, float size, sf::Color color, bool drawOutline) {
    cellShape.setPosition(x, y);
    cellShape.setSize(sf::Vector2f(size - 1, size - 1));
    cellShape.setFillColor(color);
    buffer.draw(cellShape);
}
  • void updateFPS() :
    • Met à jour l'affichage des FPS (frames per second).
void GraphicalDisplay::updateFPS() {
    float currentTime = fpsClock.restart().asSeconds();
    lastFPS = 1.f / currentTime;

    std::stringstream fpsStr;
    fpsStr << "FPS: " << static_cast<int>(lastFPS);
    fpsText.setString(fpsStr.str());
}
  • void drawInterface(const Grid& grid) :
    • Dessine l'interface utilisateur incluant les commandes et les informations de jeu (mode torique, vitesse d'itération, etc.).
void GraphicalDisplay::drawInterface(const Grid& grid) {
    std::stringstream controls;
    controls << "Controles:\n"
             << "T: Mode torique " << (grid.getToroidal() ? "(ON)" : "(OFF)") << "\n"
             << "G: Placer un Glider\n"
             << "O: Placer un obstacle\n"
             << "Espace: " << (paused ? "PAUSE" : "EN COURS") << "\n"
             << "Clic gauche: Activer/Desactiver une cellule\n"
             << "PageUp/PageDown: Vitesse [" << iterationSpeed << "ms]\n"
             << "Echap: Quitter\n"
             << "Taille: " << grid.getWidth() << "x" << grid.getHeight() << "\n"
             << "Itération: " << currentIteration << "/"
             << (maxIterations > 0 ? std::to_string(maxIterations) : "") << "\n";
    helpText.setString(controls.str());
    buffer.draw(helpText);
    buffer.draw(fpsText);
}
  • void update(const Grid& grid) :
    • Met à jour l'affichage graphique, dessine les cellules et l'interface, et gère les événements utilisateur.

GraphicalDisplay.cpp

  • void update(const Grid& grid) :
void GraphicalDisplay::update(const Grid& grid) {
    handleEvents();
    updateFPS();

    if (window.isOpen()) {
        buffer.clear(DEAD_COLOR);

        float gridWidth = static_cast<float>(window.getSize().x);
        float gridHeight = static_cast<float>(window.getSize().y);
        cellSize = std::min(gridWidth / grid.getWidth(), gridHeight / grid.getHeight());

        float offsetX = (gridWidth - (cellSize * grid.getWidth())) / 2;
        float offsetY = (gridHeight - (cellSize * grid.getHeight())) / 2;

        int startX = std::max(0, static_cast<int>(-offsetX / cellSize));
        int startY = std::max(0, static_cast<int>(-offsetY / cellSize));
        int endX = std::min(grid.getWidth(), static_cast<int>((gridWidth - offsetX) / cellSize) + 1);
        int endY = std::min(grid.getHeight(), static_cast<int>((gridHeight - offsetY) / cellSize) + 1);

        for (int y = startY; y < endY; y++) {
            for (int x = startX; x < endX; x++) {
                float posX = offsetX + x * cellSize;
                float posY = offsetY + y * cellSize;

                if (isCellVisible(posX, posY, gridWidth, gridHeight)) {
                    const Cell& cell = grid.getCellAt(x, y);
                    if (cell.isObstacleCell()) {
                        drawCell(posX, posY, cellSize, OBSTACLE_COLOR);
                    } else if (cell.getCurrentState() == CellState::ALIVE) {
                        drawCell(posX, posY, cellSize, ALIVE_COLOR);
                    } else {
                        drawCell(posX, posY, cellSize, DEAD_COLOR, true);
                    }
                }
            }
        }

        drawInterface(grid);

        buffer.display();
        sf::Sprite sprite(buffer.getTexture());
        window.clear();
        window.draw(sprite);
        window.display();
    }
}
  • void handleEvents() :
    • Gère les événements utilisateur, tels que les clics de souris et les pressions de touches, pour interagir avec le jeu (mettre en pause, ajuster la vitesse, etc.).
void GraphicalDisplay::handleEvents() {
    sf::Event event;
    while (window.pollEvent(event)) {
        switch (event.type) {
            case sf::Event::Closed:
                window.close();
                break;

            case sf::Event::KeyPressed:
                switch (event.key.code) {
                    case sf::Keyboard::Escape:
                        window.close();
                        break;

                    case sf::Keyboard::Space:
                        paused = !paused;
                        std::cout << (paused ? "Jeu en pause" : "Jeu repris") << std::endl;
                        break;

                    case sf::Keyboard::T:
                        if (grid) {
                            grid->setToroidal(!grid->getToroidal());
                            std::cout << "Mode torique : " << (grid->getToroidal() ? "activé" : "désactivé") << std::endl;
                        }
                        break;

                    case sf::Keyboard::PageUp:
                        iterationSpeed = std::max(50.0f, iterationSpeed - 50.0f);
                        std::cout << "Vitesse d'itération : " << iterationSpeed << "ms" << std::endl;
                        break;

                    case sf::Keyboard::PageDown:
                        iterationSpeed = std::min(1000.0f, iterationSpeed + 50.0f);
                        std::cout << "Vitesse d'itération : " << iterationSpeed << "ms" << std::endl;
                        break;

                    case sf::Keyboard::G:
                        if (grid) {
                            sf::Vector2i mousePos = sf::Mouse::getPosition(window);
                            int gridX = mousePos.x / cellSize;
                            int gridY = mousePos.y / cellSize;
                            if (gridX >= 0 && gridX < grid->getWidth() && gridY >= 0 && gridY < grid->getHeight()) {
                                grid->addPattern(Pattern::GLIDER, gridX, gridY);
                                std::cout << "Glider ajouté en (" << gridX << "," << gridY << ")" << std::endl;
                            }
                        }
                        break;

                    case sf::Keyboard::O:
                        if (grid) {
                            sf::Vector2i mousePos = sf::Mouse::getPosition(window);
                            int gridX = mousePos.x / cellSize;
                            int gridY = mousePos.y / cellSize;
                            if (gridX >= 0 && gridX < grid->getWidth() && gridY >= 0 && gridY < grid->getHeight()) {
                                grid->addObstacle(gridX, gridY);
                                std::cout << "Obstacle ajouté en (" << gridX << "," << gridY << ")" << std::endl;
                            }
                        }
                        break;
                }
                break;

            case sf::Event::MouseButtonPressed:
                if (event.mouseButton.button == sf::Mouse::Left && grid) {
                    sf::Vector2i mousePos = sf::Mouse::getPosition(window);
                    int gridX = mousePos.x / cellSize;
                    int gridY = mousePos.y / cellSize;
                    if (gridX >= 0 && gridX < grid->getWidth() && gridY >= 0 && gridY < grid->getHeight()) {
                        const Cell& currentCell = grid->getCellAt(gridX, gridY);
                        CellState newState = (currentCell.getCurrentState() == CellState::ALIVE)
                                         ? CellState::DEAD
                                         : CellState::ALIVE;
                        grid->setCellAt(gridX, gridY, newState);
                        std::cout << "Cellule " << (newState == CellState::ALIVE ? "activée" : "désactivée")
                                 << " en (" << gridX << "," << gridY << ")" << std::endl;
                    }
                }
                break;
        }
    }
}
  • void close() :
    • Ferme la fenêtre graphique si elle est ouverte.
void GraphicalDisplay::close() {
    if (window.isOpen()) {
        window.close();
    }
}
  • bool isWindowOpen() const :
    • Vérifie si la fenêtre graphique est ouverte.
bool GraphicalDisplay::isWindowOpen() const {
    return window.isOpen();
}

Méthodes Publics

  • void setGrid(Grid grid)* :

    • Définit la grille à afficher.
  • float getIterationSpeed() const :

    • Retourne la vitesse d'itération actuelle.
  • void setIterationSpeed(float speed) :

    • Définit la vitesse d'itération.
  • void togglePause() :

    • Met en pause ou reprend le jeu.
  • bool isPaused() const :

    • Vérifie si le jeu est en pause.
  • void setMaxIterations(int maxIterations) :

    • Définit le nombre d'itérations maximum.
  • void setIterationCount(int currentIteration) :

    • Définit le compteur d'itérations actuel.

Avec cette documentation détaillée, tu devrais avoir une bonne compréhension de la structure et des fonctionnalités de la classe GraphicalDisplay dans les fichiers GraphicalDisplay.cpp et GraphicalDisplay.h. Si tu as besoin de plus d'explications ou d'exemples, fais-le moi savoir ! 🚀📚😊

⚠️ **GitHub.com Fallback** ⚠️