diff --git a/Makefile b/Makefile index 75c1ce8..7ae3f64 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,9 @@ INC := -I include STD := -std=c++11 SFML := -lsfml-graphics -lsfml-window -lsfml-system -all: dirs compile link +all: compile link + +fresh: dirs compile link dirs: mkdir bin build diff --git a/include/GameState.h b/include/GameState.h index f5ccb13..5b0d616 100644 --- a/include/GameState.h +++ b/include/GameState.h @@ -1,22 +1,32 @@ // GameState.h #ifndef GAMESTATE_H #define GAMESTATE_H + #include +#include "Snake.h" class GameState { -private: public: - sf::VideoMode gameVideoMode; - sf::RenderWindow gameWindow; GameState(); GameState(int newHorizontal, int newVertical); - void startNewGame(); + void StartGame(void); + sf::Vector2f GetGameBoundaries(void); /* gameGridHorizontal = (videoSizeHorizontal // 25) * 25; gameGridVertical = (videoSizeVertical // 25) * 25; */ - // sf::Vector2f GetGameBoundaries(); +protected: + ; +private: + sf::RenderWindow gameWindow; + sf::VideoMode gameVideoSettings; + SnakeFood playerFood; + Snake player; + sf::Time delay; + void RegenerateFood(void); + void RunGameLoop(void); + void RenderWindow(void); }; #endif diff --git a/include/Snake.h b/include/Snake.h index aa873b3..235a0f4 100644 --- a/include/Snake.h +++ b/include/Snake.h @@ -11,9 +11,6 @@ bool GlobalCollision(sf::Vector2f object1Position, sf::Vector2f object2Position) class Snake { -private: - std::deque snakeBody; - int snakeDirection = 0; public: Snake(); Snake(sf::Vector2f head); @@ -21,10 +18,15 @@ public: sf::RectangleShape GetSnakeHead(); void DisplaySnake(sf::RenderWindow& window); void MoveSnake(SnakeFood& playerFood, sf::VideoMode gameVideoMode); - void SnakeFoodCollision(SnakeFood& snakeFood, sf::VideoMode gameVideoMode); void CheckDirection(); bool CheckBoundaries(); bool IsSelfCollision(sf::RectangleShape testRectangle); + bool IsTouchingObject(sf::RectangleShape object); +protected: + ; +private: + std::deque snakeBody; + int snakeDirection = 0; }; diff --git a/include/SnakeFood.h b/include/SnakeFood.h index 67f603a..824efb9 100644 --- a/include/SnakeFood.h +++ b/include/SnakeFood.h @@ -1,18 +1,24 @@ // SnakeFood.h #ifndef SNAKEFOOD_H #define SNAKEFOOD_H + #include #include +extern const int kGridSize; + class SnakeFood { -private: public: - sf::RectangleShape snakeFoodObject; - std::default_random_engine generator; SnakeFood(); SnakeFood(sf::Vector2f snakeFoodSize); - void GenerateNewLocation(int horizontalLocation, int verticalLocation); + void GenerateNewFood(sf::Vector2f windowSize); + sf::RectangleShape GetFoodObject(void); +protected: + ; +private: + sf::RectangleShape snakeFoodObject; + std::default_random_engine generator; int GenerateRandomNumber(int generationLimit); }; diff --git a/src/GameState.cpp b/src/GameState.cpp index f9a89a1..300ed95 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -6,42 +6,68 @@ GameState::GameState() { - sf::VideoMode tempVideoMode(1024, 725); - gameVideoMode = tempVideoMode; - sf::RenderWindow gameWindow(gameVideoMode, "SnakePlusPlus"); + delay = sf::milliseconds(100); + gameVideoSettings = sf::VideoMode(1024, 725); + gameWindow.create(gameVideoSettings, "SnakePlusPlus"); return; } -GameState::GameState(int newHorizontal, int newVertical) +GameState::GameState(int maxHorizontal, int maxVertical) { - sf::VideoMode tempVideoMode(newHorizontal, newVertical); - gameVideoMode = tempVideoMode; - sf::RenderWindow tempWindow(gameVideoMode, "SnakePlusPlus"); + delay = sf::milliseconds(100); + gameVideoSettings = sf::VideoMode(maxHorizontal, maxVertical); + gameWindow.create(gameVideoSettings, "SnakePlusPlus"); return; } -void GameState::startNewGame() +void GameState::StartGame() { - gameWindow.create(gameVideoMode, "SnakePlusPlus"); - sf::Time delay = sf::milliseconds(100); - int snakeDirection = 0; - Snake player(sf::Vector2f(25,25)); - SnakeFood playerFood(sf::Vector2f(25,25)); + gameWindow.create(gameVideoSettings, "SnakePlusPlus"); + Snake player(sf::Vector2f(kGridSize,kGridSize)); + SnakeFood playerFood(sf::Vector2f(kGridSize,kGridSize)); + RunGameLoop(); +} +sf::Vector2f GameState::GetGameBoundaries(void) +{ + sf::Vector2f boundaries; + boundaries.x = gameVideoSettings.width; + boundaries.y = gameVideoSettings.height; + return boundaries; +} + +// Generates new food until not colliding with player +void GameState::RegenerateFood(void) +{ + // Keep making new food until generating a valid spot + while (player.IsTouchingObject(playerFood.GetFoodObject())) + playerFood.GenerateNewFood(GetGameBoundaries()); + return; +} + +void GameState::RunGameLoop(void) +{ + sf::Event event; while (gameWindow.isOpen()) { - sf::Event event; while (gameWindow.pollEvent(event)) { - if ((event.type == sf::Event::Closed) || (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))) + if ((event.type == sf::Event::Closed) || + (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))) gameWindow.close(); } player.CheckDirection(); - player.MoveSnake(playerFood, gameVideoMode); - gameWindow.clear(); - player.DisplaySnake(gameWindow); - gameWindow.draw(playerFood.snakeFoodObject); - gameWindow.display(); + player.MoveSnake(playerFood, gameVideoSettings); + RegenerateFood(); + RenderWindow(); sf::sleep(delay); } } + +void GameState::RenderWindow(void) +{ + gameWindow.clear(); + player.DisplaySnake(gameWindow); + gameWindow.draw(playerFood.GetFoodObject()); + gameWindow.display(); +} diff --git a/src/Snake.cpp b/src/Snake.cpp index d1216cf..f752c23 100644 --- a/src/Snake.cpp +++ b/src/Snake.cpp @@ -5,19 +5,37 @@ #include "Snake.h" #include "SnakeFood.h" +// General constructor for snake class +Snake::Snake() +{ + 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); + return; +} + // Get a new coordinate position based on snake direction sf::Vector2f CalculateNewPosition(int direction, sf::Vector2f position) { if (direction == 0) return position; if (direction == 1) - position.x -= 25; + position.x -= kGridSize; if (direction == 2) - position.y -= 25; + position.y -= kGridSize; if (direction == 3) - position.y += 25; + position.y += kGridSize; if (direction == 4) - position.x += 25; + position.x += kGridSize; return position; } @@ -70,7 +88,7 @@ void Snake::MoveSnake(SnakeFood& snakeFood, sf::VideoMode gameVideoMode) if (CheckBoundaries()) return; newHeadPosition = CalculateNewPosition(snakeDirection, newHeadPosition); - sf::RectangleShape newBodyPart(sf::Vector2f(25,25)); + sf::RectangleShape newBodyPart(sf::Vector2f(kGridSize, kGridSize)); newBodyPart.setPosition(newHeadPosition); if (IsSelfCollision(newBodyPart)) // Do nothing if self collision { @@ -78,9 +96,8 @@ void Snake::MoveSnake(SnakeFood& snakeFood, sf::VideoMode gameVideoMode) } newBodyPart.setFillColor(sf::Color::Green); snakeBody.push_front(newBodyPart); - if (!GlobalCollision(GetSnakeHead().getPosition(), snakeFood.snakeFoodObject.getPosition())) + if (!GlobalCollision(GetSnakeHead().getPosition(), snakeFood.GetFoodObject().getPosition())) snakeBody.pop_back(); - SnakeFoodCollision(snakeFood, gameVideoMode); return; } @@ -123,30 +140,16 @@ bool Snake::IsSelfCollision(sf::RectangleShape testRectangle) return false; } -// If player collides with food then generate until no longer collided with food -void Snake::SnakeFoodCollision(SnakeFood& snakeFood, sf::VideoMode gameVideoMode) +// Checks if snake position matches object position +bool Snake::IsTouchingObject(sf::RectangleShape object) { - while(IsSelfCollision(snakeFood.snakeFoodObject)) + for (auto snakeBodyPart = snakeBody.cbegin(); snakeBodyPart != snakeBody.cend(); ++snakeBodyPart) { - snakeFood.GenerateNewLocation(gameVideoMode.width, gameVideoMode.height); + if ((*snakeBodyPart).getPosition().x != object.getPosition().x) + continue; + if ((*snakeBodyPart).getPosition().y != object.getPosition().y) + continue; + return true; } - return; -} - -// General constructor for snake class -Snake::Snake() -{ - sf::RectangleShape newBodyPart(sf::Vector2f(25,25)); - newBodyPart.setFillColor(sf::Color::Green); - snakeBody.push_back(newBodyPart); - return; -} - -// Constructor for snake with position -Snake::Snake(sf::Vector2f head) -{ - sf::RectangleShape newBodyPart(head); - newBodyPart.setFillColor(sf::Color::Green); - snakeBody.push_back(newBodyPart); - return; + return false; } diff --git a/src/SnakeFood.cpp b/src/SnakeFood.cpp index 4a1dd0f..ff8f525 100644 --- a/src/SnakeFood.cpp +++ b/src/SnakeFood.cpp @@ -2,11 +2,12 @@ #include #include #include "SnakeFood.h" -#include "Snake.h" + +const int kGridSize = 25; SnakeFood::SnakeFood() { - snakeFoodObject.setSize(sf::Vector2f(25,25)); + snakeFoodObject.setSize(sf::Vector2f(kGridSize,kGridSize)); snakeFoodObject.setFillColor(sf::Color::Red); } @@ -16,26 +17,31 @@ SnakeFood::SnakeFood(sf::Vector2f snakeFoodSize) snakeFoodObject.setFillColor(sf::Color::Red); } -void SnakeFood::GenerateNewLocation(int horizontalLocation, int verticalLocation) +// Returns a new food object for the snakeFood +void SnakeFood::GenerateNewFood(sf::Vector2f windowSize) { sf::Vector2f newPosition; - newPosition.x = GenerateRandomNumber(horizontalLocation); - newPosition.y = GenerateRandomNumber(verticalLocation); - if (GlobalCollision(snakeFoodObject.getPosition(), newPosition)) - { - std::cout << "Location error: " << newPosition.x << " " << newPosition.y << '\n'; - throw std::runtime_error("Error! New generation on same location"); - } + newPosition.x = GenerateRandomNumber(windowSize.x); + newPosition.y = GenerateRandomNumber(windowSize.y); snakeFoodObject.setPosition(newPosition); - return; + // if (GlobalCollision(snakeFoodObject.getPosition(), newPosition)) + // { + // std::cout << "Location error: " << newPosition.x << " " << newPosition.y << '\n'; + // throw std::runtime_error("Error! New generation on same location"); + // } } +sf::RectangleShape SnakeFood::GetFoodObject(void) +{ + return snakeFoodObject; +} +// Returns a newly generated number int SnakeFood::GenerateRandomNumber(int generationLimit) { int generatedNumber; std::uniform_int_distribution<> distribution(0, generationLimit); generatedNumber = distribution(generator); - generatedNumber -= (generatedNumber % 25); + generatedNumber -= (generatedNumber % kGridSize); return generatedNumber; } diff --git a/src/main.cpp b/src/main.cpp index bd09bb5..7a1a501 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,6 @@ int main() { - GameState newGame; - newGame.startNewGame(); + GameState game; + game.StartGame(); }