From 3ee01d936b4d38f7bafb54afb16ed165d3e31be4 Mon Sep 17 00:00:00 2001 From: TriantaTV Date: Mon, 13 Mar 2023 08:24:56 -0500 Subject: [PATCH] Game finishes, but is buggy. Proper grid needed --- include/GameState.h | 2 ++ include/Snake.h | 6 +++++- src/GameState.cpp | 41 ++++++++++++++++++++++++++++++++++++-- src/Snake.cpp | 48 +++++++++++++++++++++++++++++++-------------- 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/include/GameState.h b/include/GameState.h index adca85d..d6eb2a7 100644 --- a/include/GameState.h +++ b/include/GameState.h @@ -20,7 +20,9 @@ private: SnakeFood playerFood; Snake player; sf::Time delay; + void DisplayEndScreen(void); void GetKeyboardInput(void); + bool PlayerWantsToContinue(void); void RegenerateFood(void); void RunGameLoop(void); void RenderWindow(void); diff --git a/include/Snake.h b/include/Snake.h index 63f2edf..b2c81bb 100644 --- a/include/Snake.h +++ b/include/Snake.h @@ -10,21 +10,25 @@ class Snake { public: + bool gameFinished = false; Snake(void); - Snake(sf::Vector2f head); void DisplaySnake(sf::RenderWindow& window); sf::RectangleShape GetSnakeHead(void); sf::Vector2f GetSnakeHeadPosition(void); bool IsTouchingObject(sf::RectangleShape object); void MoveSnake(SnakeFood* playerFood); + void Reset(void); void UpdateDirection(int newDirection); protected: ; private: std::deque snakeBody; + sf::Vector2f bodyPartSize; int snakeDirection = 0; + void AddBodyPart(sf::RectangleShape newBodyPart); sf::Vector2f CalculateNewPosition(sf::Vector2f position); bool CheckBoundaries(void); + void CreateHead(void); bool IsSelfCollision(sf::RectangleShape testRectangle); }; diff --git a/src/GameState.cpp b/src/GameState.cpp index 13b05f4..9a4350b 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -24,12 +24,29 @@ GameState::GameState(int maxHorizontal, int maxVertical) void GameState::StartGame() { gameWindow.create(gameVideoSettings, "SnakePlusPlus"); - Snake player(sf::Vector2f(kGridSize,kGridSize)); - SnakeFood playerFood(sf::Vector2f(kGridSize,kGridSize)); RunGameLoop(); return; } +void GameState::DisplayEndScreen(void) +{ + gameWindow.clear(); + sf::Vector2f textPosition(GetGameBoundaries()); + textPosition.x = textPosition.x / 2; + textPosition.y = textPosition.y / 2; + sf::Text gameOverText; + gameOverText.setString("Game Over"); + gameOverText.setCharacterSize(30); + gameOverText.setPosition(textPosition); + gameWindow.draw(gameOverText); + gameWindow.display(); + if (!PlayerWantsToContinue()) + return; + player.Reset(); + gameWindow.clear(); + return; +} + sf::Vector2f GameState::GetGameBoundaries(void) { sf::Vector2f boundaries; @@ -58,6 +75,24 @@ void GameState::GetKeyboardInput(void) return; } +bool GameState::PlayerWantsToContinue(void) +{ + sf::Event event; + while (true) + { + while (gameWindow.pollEvent(event)) + { + if ((event.type == sf::Event::Closed) || + (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))) + gameWindow.close(); + return false; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Enter)) + return true; + sf::sleep(delay); + } +} + // Generates new food until not colliding with player void GameState::RegenerateFood(void) { @@ -86,5 +121,7 @@ void GameState::RenderWindow(void) player.DisplaySnake(gameWindow); gameWindow.draw(playerFood.GetFoodObject()); gameWindow.display(); + if (player.gameFinished) + DisplayEndScreen(); return; } diff --git a/src/Snake.cpp b/src/Snake.cpp index b343abb..3420fcc 100644 --- a/src/Snake.cpp +++ b/src/Snake.cpp @@ -9,18 +9,8 @@ // General constructor for snake class Snake::Snake(void) { - sf::RectangleShape newBodyPart(sf::Vector2f(kGridSize, kGridSize)); - newBodyPart.setFillColor(sf::Color::Green); - snakeBody.push_back(newBodyPart); - return; -} - -// Constructor for snake with position -Snake::Snake(sf::Vector2f headSize) -{ - sf::RectangleShape newBodyPart(headSize); - newBodyPart.setFillColor(sf::Color::Green); - snakeBody.push_back(newBodyPart); + bodyPartSize = sf::Vector2f(kGridSize, kGridSize); + CreateHead(); return; } @@ -67,27 +57,48 @@ void Snake::MoveSnake(SnakeFood* snakeFood) { // TODO: Add losing on wall collision if (CheckBoundaries()) // Wall collision + { + gameFinished = true; return; + } sf::Vector2f newHeadPosition; newHeadPosition = CalculateNewPosition(GetSnakeHeadPosition()); sf::RectangleShape newBodyPart(sf::Vector2f(kGridSize, kGridSize)); newBodyPart.setPosition(newHeadPosition); // TODO: Add losing on self collision - if (IsSelfCollision(newBodyPart)) // Snake collision + if (IsSelfCollision(newBodyPart) && (snakeBody.size() > 1)) // Snake collision + { + gameFinished = true; return; - newBodyPart.setFillColor(sf::Color::Green); - snakeBody.push_front(newBodyPart); + } + if (IsSelfCollision(newBodyPart)) + return; + AddBodyPart(newBodyPart); if (!GlobalCollision(GetSnakeHeadPosition(), snakeFood->GetFoodObjectPosition())) snakeBody.pop_back(); return; } +void Snake::Reset(void) +{ + snakeBody.clear(); + gameFinished = false; + CreateHead(); + snakeDirection = kRight; +} + void Snake::UpdateDirection(int newDirection) { snakeDirection = newDirection; return; } +void Snake::AddBodyPart(sf::RectangleShape newBodyPart) +{ + newBodyPart.setFillColor(sf::Color::Green); + snakeBody.push_front(newBodyPart); +} + // Get a new coordinate position based on snake direction sf::Vector2f Snake::CalculateNewPosition(sf::Vector2f position) { @@ -119,6 +130,13 @@ bool Snake::CheckBoundaries(void) return false; } +void Snake::CreateHead(void) +{ + sf::RectangleShape newBodyPart(bodyPartSize); + newBodyPart.setFillColor(sf::Color::Green); + snakeBody.push_front(newBodyPart); +} + // Test for snake self collision bool Snake::IsSelfCollision(sf::RectangleShape testRectangle) {