diff --git a/src/jeu.cpp b/src/jeu.cpp index 67ec1b1..2bd15c2 100644 --- a/src/jeu.cpp +++ b/src/jeu.cpp @@ -1,6 +1,8 @@ #include "jeu.hpp" #include +#define APPLE_VALUE 10 + using namespace std; Jeu::Jeu() { @@ -65,9 +67,13 @@ bool Jeu::init() { return true; } -void Jeu::tick() { - if (pause) // Game is paused, don't do anything - return; +/** + * The main game logic, called periodically + * @return true if the player lost during this tick + */ +bool Jeu::tick() { + if (pause || gameOver) // Game is paused or finished, don't do anything + return false; if (!directionsBuffer.empty()) { dirSnake = directionsBuffer.front(); @@ -86,10 +92,9 @@ void Jeu::tick() { snake.push_front(posTest); // Add the new head if (posTest == applePos) { + // The snake eats the apple, increase the score and place a new apple + increaseScore(APPLE_VALUE); - increaseScore(1); - //std::cout << "Snake eats the apple!" << std::endl; - // The snake eats the apple, place a new apple std::uniform_int_distribution<> distr(0, map.getWidth() - 1); int attempts = 0; do { @@ -97,7 +102,8 @@ void Jeu::tick() { applePos.y = distr(gen); attempts++; if (attempts > 2 * map.getWidth() * map.getHeight()) { - break; // TODO: lose / win condition ? + gameOver = true; + return true; } } while (!posValide(applePos, APPLE_SPAWN)); // Don't remove the last element of the snake to make it grow @@ -107,9 +113,12 @@ void Jeu::tick() { } } else { // Game over - snake.clear(); // TODO: lose condition - game_over = -1; // perdu + snake.clear(); + gameOver = true; // perdu + return true; } + + return false; } const list *Jeu::getSnake() const { diff --git a/src/jeu.hpp b/src/jeu.hpp index 619500c..fcb9bf3 100644 --- a/src/jeu.hpp +++ b/src/jeu.hpp @@ -16,11 +16,9 @@ class Jeu { Position applePos = Position(-1, -1); std::mt19937 gen; bool pause = false; - -private: + bool gameOver = false; int score = 0; - public: Jeu(); @@ -34,7 +32,7 @@ class Jeu { bool init(); - void tick(); + bool tick(); const std::list *getSnake() const; @@ -59,10 +57,14 @@ class Jeu { int getScore() const { return score; } - void increaseScore(int point) { - score=score+point; + + void increaseScore(const int point) { + score = score + point; + } + + bool isGameOver() const { + return gameOver; } - int game_over; // 0: not over, 1: win, -1: lose }; #endif diff --git a/src/screens/endgamescreen.cpp b/src/screens/endgamescreen.cpp index a912597..22d118c 100644 --- a/src/screens/endgamescreen.cpp +++ b/src/screens/endgamescreen.cpp @@ -1,20 +1,34 @@ +#include "endgamescreen.hpp" +#include -#include "endgamescreen.hpp" +EndGameScreen::EndGameScreen(const int score, QWidget *parent) + : QWidget(parent), scoreLabel(new QLabel(this)) { + // Load custom font + const int id = QFontDatabase::addApplicationFont(":/images/game_played.otf"); + const QString family = QFontDatabase::applicationFontFamilies(id).at(0); + QFont snakefont(family); + snakefont.setPointSize(36); -EndGameScreen::EndGameScreen(int score, QWidget *parent) - : QWidget(parent), scoreLabel(new QLabel(this)) { // Layout vertical pour organiser les widgets - QVBoxLayout *layout = new QVBoxLayout(this); + const auto layout = new QVBoxLayout(this); + + // Étiquette de texte pour afficher le message de fin de jeu + const auto endGameLabel = new QLabel("Game Over!", this); + endGameLabel->setFont(snakefont); // Police en gras et taille 36 + endGameLabel->setAlignment(Qt::AlignCenter); // Centrez le texte // Étiquette de texte pour afficher le score - QLabel *scoreLabel = new QLabel("Score: " + QString::number(score), this); + const auto scoreLabel = new QLabel("Score: " + QString::number(score), this); scoreLabel->setFont(QFont("Arial", 24, QFont::Bold)); // Police en gras et taille 24 scoreLabel->setAlignment(Qt::AlignCenter); // Centrez le texte // Ajouter l'étiquette de score au layout + layout->addStretch(); + layout->addWidget(endGameLabel); layout->addWidget(scoreLabel); + layout->addStretch(); // Définir le layout pour la fenêtre setLayout(layout); -} \ No newline at end of file +} diff --git a/src/screens/gamescreen.cpp b/src/screens/gamescreen.cpp index 70b074c..f0191b7 100644 --- a/src/screens/gamescreen.cpp +++ b/src/screens/gamescreen.cpp @@ -12,7 +12,7 @@ GameScreen::GameScreen(QWidget *parent, const QString &file_info): QWidget(paren auto *layout = new QVBoxLayout; auto *mapNameLabel = new QLabel(jeu.getMap().getName() + " by " + jeu.getMap().getAuthor(), this); - scoreLabel = new QLabel("Score: 0", this); + scoreLabel = new QLabel("Score: 0", this); layout->addWidget(mapNameLabel); layout->addWidget(gameArea); @@ -45,11 +45,9 @@ GameScreen::GameScreen(QWidget *parent, const QString &file_info): QWidget(paren pauseLayout->setSpacing(0); pauseLayout->addWidget(pauseLabel); pauseLayout->addWidget(resumeLabel); - - } -void GameScreen::resizeEvent(QResizeEvent* event) { +void GameScreen::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); pauseOverlay->resize(event->size()); } @@ -67,7 +65,7 @@ void GameScreen::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Down) jeu.setDirection(BAS); - if (event->key() == Qt::Key_P) { + if (event->key() == Qt::Key_P || event->key() == Qt::Key_Escape) { jeu.togglePause(); if (jeu.isPaused()) { @@ -77,7 +75,6 @@ void GameScreen::keyPressEvent(QKeyEvent *event) { } } - update(); } @@ -85,31 +82,16 @@ void GameScreen::updateScoreLabel() { scoreLabel->setText("Score: " + QString::number(jeu.getScore())); } -void GameScreen::endGame() { - emit gameOver(jeu.getScore()); -} - /** * Tick the game */ void GameScreen::handleTimer() { - jeu.tick(); - - updateScoreLabel(); - - if (jeu.game_over != 0) { - // Game over - if (jeu.game_over == 1) { - // Win - std::cout << "You win!" << std::endl; - } else { - // Lose - std::cout << "You lose!" << std::endl; - emit gameOver(jeu.getScore()); - } - + if(jeu.tick()) { // Tick the game + // The player lost this tick + emit gameOver(jeu.getScore()); } + updateScoreLabel(); - update(); + update(); // Redraw the screen } diff --git a/src/screens/gamescreen.hpp b/src/screens/gamescreen.hpp index 15662fa..bb56721 100644 --- a/src/screens/gamescreen.hpp +++ b/src/screens/gamescreen.hpp @@ -22,17 +22,15 @@ class GameScreen final : public QWidget { void handleTimer(); - protected: void keyPressEvent(QKeyEvent *) override; private: QLabel *scoreLabel; + void updateScoreLabel(); - void endGame(); signals: void gameOver(int score); - }; #endif //GAMESCREEN_HPP diff --git a/src/screens/snakewindow.cpp b/src/screens/snakewindow.cpp index 59b666f..bda89f2 100644 --- a/src/screens/snakewindow.cpp +++ b/src/screens/snakewindow.cpp @@ -50,6 +50,8 @@ SnakeWindow::SnakeWindow(QWidget *pParent, const Qt::WindowFlags flags) gameScreen = new GameScreen(this, fileName); stackedWidget->addWidget(gameScreen); stackedWidget->setCurrentWidget(gameScreen); + + connect(gameScreen, &GameScreen::gameOver, this, &SnakeWindow::handleGameOver); } }); @@ -107,6 +109,8 @@ void SnakeWindow::handlePlayMapClicked() { gameScreen = new GameScreen(this, fileName); stackedWidget->addWidget(gameScreen); stackedWidget->setCurrentWidget(gameScreen); + + connect(gameScreen, &GameScreen::gameOver, this, &SnakeWindow::handleGameOver); }); } @@ -149,11 +153,8 @@ void SnakeWindow::handleExitClicked() { QApplication::quit(); } -void SnakeWindow::handleGameOver(int score) { +void SnakeWindow::handleGameOver(const int score) { // Switch to the end game screen when the game is over - delete gameScreen; - gameScreen = nullptr; - endGameScreen = new EndGameScreen(score, this); setCentralWidget(endGameScreen); diff --git a/src/screens/snakewindow.hpp b/src/screens/snakewindow.hpp index c69e584..6505f8d 100644 --- a/src/screens/snakewindow.hpp +++ b/src/screens/snakewindow.hpp @@ -19,7 +19,7 @@ class SnakeWindow final : public QMainWindow { GameScreen *gameScreen{}; BrowseMapScreen *browseMapScreen{}; EditorScreen *editorScreen{}; - + EndGameScreen *endGameScreen{}; public: explicit SnakeWindow(QWidget *pParent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); @@ -40,9 +40,6 @@ public slots: showFullScreen(); } } -private : - EndGameScreen *endGameScreen; - }; #endif