diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/Arial.ttf b/Arial.ttf new file mode 100644 index 0000000..7ff88f2 Binary files /dev/null and b/Arial.ttf differ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f260804 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.10) + +project( + snakeplusplus + LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 11 CACHE STRING "The C++ standard to use") +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) + +include_directories(${snakeplusplus_SOURCE_DIR}/src) + +add_subdirectory(src) + diff --git a/Makefile b/Makefile deleted file mode 100644 index 16244f8..0000000 --- a/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -INC := -I include -STD := -std=c++11 -SFML := -lsfml-graphics -lsfml-window -lsfml-system - -all: compile link - -fresh: dirs compile link - -compile: - g++ $(INC) $(STD) -c -o build/main.o src/main.cpp - g++ $(INC) $(STD) -c -o build/Common.o src/Common.cpp - g++ $(INC) $(STD) -c -o build/GameState.o src/GameState.cpp - g++ $(INC) $(STD) -c -o build/Snake.o src/Snake.cpp - g++ $(INC) $(STD) -c -o build/SnakeFood.o src/SnakeFood.cpp - -dirs: - mkdir bin build - -link: - g++ build/*.o -o bin/SnakePlusPlus $(SFML) - -clean: - rm bin/*.o build/*.out \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 3e5d1f2..3ffd615 --- a/README.md +++ b/README.md @@ -14,6 +14,15 @@ Prerequisites Clone the repository and compile it using: git clone https://github.com/TriantaTV/snakeplusplus.git - make -The game is output into the `bin` folder, simply run the game and enjoy! +In order to compile the project, simply run these two commands: + + cmake -B build -S . + cmake --build build + +## Running the Project +The program should now be compiled at ./build/bin/snakeplusplus + +Simply run the program using: + + build/bin/snakeplusplus diff --git a/include/Common.h b/include/Common.h deleted file mode 100644 index 22c2353..0000000 --- a/include/Common.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#include - -const int kGridSize = 25; - -enum PlayerDirection -{ - kLeft = 1, - kUp = 2, - kDown = 3, - kRight = 4 -}; - -bool GlobalCollision(sf::Vector2f object1Position, sf::Vector2f object2Position); - -#endif \ No newline at end of file diff --git a/include/GameState.h b/include/GameState.h deleted file mode 100644 index adca85d..0000000 --- a/include/GameState.h +++ /dev/null @@ -1,29 +0,0 @@ -// GameState.h -#ifndef GAMESTATE_H -#define GAMESTATE_H - -#include -#include "Snake.h" - -class GameState -{ -public: - GameState(); - GameState(int newHorizontal, int newVertical); - void StartGame(void); - sf::Vector2f GetGameBoundaries(void); -protected: - ; -private: - sf::RenderWindow gameWindow; - sf::VideoMode gameVideoSettings; - SnakeFood playerFood; - Snake player; - sf::Time delay; - void GetKeyboardInput(void); - void RegenerateFood(void); - void RunGameLoop(void); - void RenderWindow(void); -}; - -#endif diff --git a/include/Snake.h b/include/Snake.h deleted file mode 100644 index 63f2edf..0000000 --- a/include/Snake.h +++ /dev/null @@ -1,32 +0,0 @@ -// Snake.h -#ifndef SNAKE_H -#define SNAKE_H - -#include -#include -#include "SnakeFood.h" - - -class Snake -{ -public: - 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 UpdateDirection(int newDirection); -protected: - ; -private: - std::deque snakeBody; - int snakeDirection = 0; - sf::Vector2f CalculateNewPosition(sf::Vector2f position); - bool CheckBoundaries(void); - bool IsSelfCollision(sf::RectangleShape testRectangle); -}; - - -#endif diff --git a/include/SnakeFood.h b/include/SnakeFood.h deleted file mode 100644 index 06b21cb..0000000 --- a/include/SnakeFood.h +++ /dev/null @@ -1,24 +0,0 @@ -// SnakeFood.h -#ifndef SNAKEFOOD_H -#define SNAKEFOOD_H - -#include -#include - -class SnakeFood -{ -public: - SnakeFood(); - SnakeFood(sf::Vector2f snakeFoodSize); - void GenerateNewFood(sf::Vector2f windowSize); - sf::RectangleShape GetFoodObject(void); - sf::Vector2f GetFoodObjectPosition(void); -protected: - ; -private: - sf::RectangleShape snakeFoodObject; - std::default_random_engine generator; - int GenerateRandomNumber(int generationLimit); -}; - -#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..02db7fb --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,13 @@ +find_package(SFML COMPONENTS graphics window system REQUIRED) + +add_executable(snakeplusplus + ./main.cpp + ./gamestate.cpp + ./snake.cpp + ./playerinterface.cpp +) + +target_include_directories(snakeplusplus PUBLIC ${CMAKE_CURRENT_LIST_DIR}) + +target_link_libraries(snakeplusplus sfml-graphics) + diff --git a/src/Common.cpp b/src/Common.cpp deleted file mode 100644 index e8887a6..0000000 --- a/src/Common.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "Common.h" - -// Test for collision between two object positions -bool GlobalCollision(sf::Vector2f object1Position, sf::Vector2f object2Position) -{ - if (object1Position.x != object2Position.x) - return false; - if (object1Position.y != object2Position.y) - return false; - return true; -} \ No newline at end of file diff --git a/src/GameState.cpp b/src/GameState.cpp deleted file mode 100644 index 13b05f4..0000000 --- a/src/GameState.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// GameState.cpp -#include -#include -#include "Common.h" -#include "Snake.h" -#include "GameState.h" - -GameState::GameState() -{ - delay = sf::milliseconds(75); - gameVideoSettings = sf::VideoMode(1025, 725); - gameWindow.create(gameVideoSettings, "SnakePlusPlus"); - return; -} - -GameState::GameState(int maxHorizontal, int maxVertical) -{ - delay = sf::milliseconds(75); - gameVideoSettings = sf::VideoMode(maxHorizontal, maxVertical); - gameWindow.create(gameVideoSettings, "SnakePlusPlus"); - return; -} - -void GameState::StartGame() -{ - gameWindow.create(gameVideoSettings, "SnakePlusPlus"); - Snake player(sf::Vector2f(kGridSize,kGridSize)); - SnakeFood playerFood(sf::Vector2f(kGridSize,kGridSize)); - RunGameLoop(); - return; -} - -sf::Vector2f GameState::GetGameBoundaries(void) -{ - sf::Vector2f boundaries; - boundaries.x = gameVideoSettings.width; - boundaries.y = gameVideoSettings.height; - return boundaries; -} - -void GameState::GetKeyboardInput(void) -{ - sf::Event event; - while (gameWindow.pollEvent(event)) - { - if ((event.type == sf::Event::Closed) || - (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))) - gameWindow.close(); - } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) - player.UpdateDirection(kLeft); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) - player.UpdateDirection(kUp); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) - player.UpdateDirection(kDown); - if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) - player.UpdateDirection(kRight); - return; -} - -// 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) -{ - while (gameWindow.isOpen()) - { - GetKeyboardInput(); - player.MoveSnake(&playerFood); - RegenerateFood(); - RenderWindow(); - sf::sleep(delay); - } - return; -} - -void GameState::RenderWindow(void) -{ - gameWindow.clear(); - player.DisplaySnake(gameWindow); - gameWindow.draw(playerFood.GetFoodObject()); - gameWindow.display(); - return; -} diff --git a/src/Snake.cpp b/src/Snake.cpp deleted file mode 100644 index b343abb..0000000 --- a/src/Snake.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// Snake.cpp -#include -#include -#include -#include "Common.h" -#include "Snake.h" -#include "SnakeFood.h" - -// 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); - return; -} - -// Iterate through snake deque and draw to window -void Snake::DisplaySnake(sf::RenderWindow& window) -{ - for (auto snakeBodyPart = snakeBody.cbegin(); snakeBodyPart != snakeBody.cend(); ++snakeBodyPart) - window.draw(*snakeBodyPart); - return; -} - -// Return the RectangleShape head of snake -sf::RectangleShape Snake::GetSnakeHead(void) -{ - sf::RectangleShape head; - head = snakeBody.front(); - return head; -} - -// Return the Vector2f head of snake -sf::Vector2f Snake::GetSnakeHeadPosition(void) -{ - sf::Vector2f position; - position = snakeBody.front().getPosition(); - return position; -} - -// Checks if snake position matches object position -bool Snake::IsTouchingObject(sf::RectangleShape object) -{ - for (auto snakeBodyPart = snakeBody.cbegin(); snakeBodyPart != snakeBody.cend(); ++snakeBodyPart) - { - if ((*snakeBodyPart).getPosition().x != object.getPosition().x) - continue; - if ((*snakeBodyPart).getPosition().y != object.getPosition().y) - continue; - return true; - } - return false; -} - -// Move snake based on direction and check for collision -void Snake::MoveSnake(SnakeFood* snakeFood) -{ - // TODO: Add losing on wall collision - if (CheckBoundaries()) // Wall collision - 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 - return; - newBodyPart.setFillColor(sf::Color::Green); - snakeBody.push_front(newBodyPart); - if (!GlobalCollision(GetSnakeHeadPosition(), snakeFood->GetFoodObjectPosition())) - snakeBody.pop_back(); - return; -} - -void Snake::UpdateDirection(int newDirection) -{ - snakeDirection = newDirection; - return; -} - -// Get a new coordinate position based on snake direction -sf::Vector2f Snake::CalculateNewPosition(sf::Vector2f position) -{ - if (snakeDirection == 0) - return position; - if (snakeDirection == kLeft) - position.x -= kGridSize; - if (snakeDirection == kUp) - position.y -= kGridSize; - if (snakeDirection == kDown) - position.y += kGridSize; - if (snakeDirection == kRight) - position.x += kGridSize; - return position; -} - -// Check snake head for running into boundaries -bool Snake::CheckBoundaries(void) -{ - if (snakeBody.front().getPosition().x == 0 && snakeDirection == kLeft) - return true; - if (snakeBody.front().getPosition().y == 0 && snakeDirection == kUp) - return true; - // TODO: Change boundaries to not be hard-coded - if (snakeBody.front().getPosition().y > 675 && snakeDirection == kDown) - return true; - if (snakeBody.front().getPosition().x > 975 && snakeDirection == kRight) - return true; - return false; -} - -// Test for snake self collision -bool Snake::IsSelfCollision(sf::RectangleShape testRectangle) -{ - for (auto snakeBodyPart = snakeBody.cbegin(); snakeBodyPart != snakeBody.cend(); ++snakeBodyPart) - if (GlobalCollision(testRectangle.getPosition(), (*snakeBodyPart).getPosition())) - return true; - return false; -} diff --git a/src/SnakeFood.cpp b/src/SnakeFood.cpp deleted file mode 100644 index b1989e4..0000000 --- a/src/SnakeFood.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// SnakeFood.cpp -#include -#include -#include "Common.h" -#include "SnakeFood.h" - - -SnakeFood::SnakeFood() -{ - snakeFoodObject.setSize(sf::Vector2f(kGridSize, kGridSize)); - snakeFoodObject.setFillColor(sf::Color::Red); - return; -} - -SnakeFood::SnakeFood(sf::Vector2f snakeFoodSize) -{ - snakeFoodObject.setSize(snakeFoodSize); - snakeFoodObject.setFillColor(sf::Color::Red); - return; -} - -// Returns a new food object for the snakeFood -void SnakeFood::GenerateNewFood(sf::Vector2f windowSize) -{ - sf::Vector2f newPosition; - newPosition.x = GenerateRandomNumber(windowSize.x); - newPosition.y = GenerateRandomNumber(windowSize.y); - snakeFoodObject.setPosition(newPosition); - return; -} - -sf::RectangleShape SnakeFood::GetFoodObject(void) -{ - return snakeFoodObject; -} - -sf::Vector2f SnakeFood::GetFoodObjectPosition(void) -{ - return snakeFoodObject.getPosition(); -} - -// Returns a newly generated number -int SnakeFood::GenerateRandomNumber(int generationLimit) -{ - int generatedNumber; - std::uniform_int_distribution<> distribution(0, generationLimit); - generatedNumber = distribution(generator); - generatedNumber -= (generatedNumber % kGridSize); - return generatedNumber; -} diff --git a/src/common.hpp b/src/common.hpp new file mode 100755 index 0000000..ef440c9 --- /dev/null +++ b/src/common.hpp @@ -0,0 +1,13 @@ +#ifndef COMMON_HPP +#define COMMON_HPP + +enum PlayerDirection +{ + kNone = 0, + kLeft = 1, + kUp = 2, + kDown = 3, + kRight = 4 +}; + +#endif diff --git a/src/gamestate.cpp b/src/gamestate.cpp new file mode 100755 index 0000000..51a5470 --- /dev/null +++ b/src/gamestate.cpp @@ -0,0 +1,134 @@ +// GameState.cpp +#include +#include +#include +#include +#include +#include "common.hpp" +#include "playerinterface.hpp" +#include "gamestate.hpp" + +namespace snakeplusplus +{ + GameEngine::GameEngine() + { + return; + } + + void GameEngine::StartGame() + { + //ApplySettings(); + PrepareGameBoard(); + graphics.StartGameWindow(); + GameLoop(); + return; + } + + void GameEngine::GameLoop(void) + { + while (graphics.IsOpen()) + { + if (isGameOver) + { + graphics.CheckContinue(); + isGameOver = 0; + } + UpdatePlayerSpeed(); + PlaceNewSnakePart(MovePlayer()); + RegenerateFood(); + graphics.DisplayGameState(gameBoard); + } + return; + } + + sf::Vector2f GameEngine::MovePlayer(void) + { + sf::Vector2f newHeadPosition; + newHeadPosition.x = player.headLocation.x + player.speed.x; + newHeadPosition.y = player.headLocation.y + player.speed.y; + return newHeadPosition; + } + + sf::Vector2f GameEngine::GetGameBoundaries(void) + { + return graphics.gameBoundaries; + } + + void GameEngine::PlaceNewSnakePart(sf::Vector2f location) + { + try + { + char* locationState; + locationState = &gameBoard.at(location.y).at(location.x); + if (*locationState == 'O' && player.body.size() > 1) + isGameOver = true; // Game should end (Snake touching snake) + *locationState = 'O'; + player.body.push(locationState); + player.headLocation = location; + if (playerFood.location != location) + player.Pop(); + } catch (const std::out_of_range& error) { + isGameOver = true; // Snake ran into edge + exit(0); + } + } + + // Generates new food until not colliding with player + void GameEngine::RegenerateFood(void) + { + sf::Vector2f newLocation = playerFood.location; + bool isUpdated = false; + // Keep making new food until generating a valid spot + while (gameBoard.at(newLocation.y).at(newLocation.x) == 'O') + { + isUpdated = true; + playerFood.GenerateNewFood(GetGameBoundaries()); + newLocation = playerFood.location; + } + if (isUpdated) + gameBoard.at(newLocation.y).at(newLocation.x) = 'X'; + return; + } + + void GameEngine::PrepareGameBoard(void) + { + gameBoard.clear(); + sf::Vector2f boardDimensions = GetGameBoundaries(); + gameBoard.resize(boardDimensions.y, std::vector (boardDimensions.x, ' ')); + player.headLocation.x = 4; + player.headLocation.y = 5; + char* locationState = &gameBoard.at(player.headLocation.y).at(player.headLocation.x); + player.body.push(locationState); + *player.body.front() = 'O'; + playerFood.location.x = 2; + playerFood.location.y = 2; + playerFood.food = &gameBoard.at(2).at(2); + *playerFood.food = 'X'; + return; + } + + void GameEngine::UpdatePlayerSpeed(void) + { + PlayerDirection input = controls.GetPlayerInput(); + switch (input) { + case kUp: + player.speed.x = 0; + player.speed.y = -1; + break; + case kLeft: + player.speed.x = -1; + player.speed.y = 0; + break; + case kRight: + player.speed.x = 1; + player.speed.y = 0; + break; + case kDown: + player.speed.x = 0; + player.speed.y = 1; + break; + default: + break; + } + } +} diff --git a/src/gamestate.hpp b/src/gamestate.hpp new file mode 100755 index 0000000..238aa4b --- /dev/null +++ b/src/gamestate.hpp @@ -0,0 +1,36 @@ +// GameState.h +#ifndef GAMESTATE_HPP +#define GAMESTATE_HPP + +#include +#include +#include "snake.hpp" +#include "playerinterface.hpp" + +namespace snakeplusplus +{ + class GameEngine + { + public: + GameEngine(); + void StartGame(void); + sf::Vector2f GetGameBoundaries(void); + private: + std::vector< std::vector > gameBoard; + PlayerInput controls; + PlayerOutput graphics; + Snake player; + Food playerFood; + bool useSFML = 1; + bool isGameOver = 0; + void DisplayEndScreen(void); + void GameLoop(void); + sf::Vector2f MovePlayer(void); + void PlaceNewSnakePart(sf::Vector2f location); + void RegenerateFood(void); + void PrepareGameBoard(void); + void UpdatePlayerSpeed(); + }; +} + +#endif diff --git a/src/main.cpp b/src/main.cpp old mode 100644 new mode 100755 index 7a1a501..854534f --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ -#include "GameState.h" +#include "gamestate.hpp" -int main() +int main(void) { - GameState game; + snakeplusplus::GameEngine game; game.StartGame(); } diff --git a/src/playerinterface.cpp b/src/playerinterface.cpp new file mode 100755 index 0000000..8e297d4 --- /dev/null +++ b/src/playerinterface.cpp @@ -0,0 +1,151 @@ +#include "playerinterface.hpp" +#include +#include +#include + +namespace snakeplusplus +{ + PlayerInput::PlayerInput(void) + { + lastPlayerInput = kNone; + } + + PlayerDirection PlayerInput::GetPlayerInput(void) + { + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) + lastPlayerInput = kLeft; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) + lastPlayerInput = kUp; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) + lastPlayerInput = kDown; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) + lastPlayerInput = kRight; + return lastPlayerInput; + } + + bool PlayerOutput::IsOpen(void) + { + return gameWindow.isOpen(); + } + + PlayerOutput::PlayerOutput(void) + { + float kWidth = 1025; + float kHeight = 725; + float kBoardWidth = kWidth / kGridSize; + float kBoardHeight = kHeight / kGridSize; + gameBoundaries = sf::Vector2f(kBoardWidth, kBoardHeight); + gameVideoSettings = sf::VideoMode(kWidth, kHeight); + drawObject.setSize(sf::Vector2f(kGridSize, kGridSize)); + return; + } + + void PlayerOutput::CheckContinue(void) + { + sf::Event event; + DisplayEndScreen(); + while (true) + { + gameWindow.pollEvent(event); + if ((event.type == sf::Event::Closed) || + (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))) + { + gameWindow.close(); + return; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Enter)) { return; } + sf::sleep(delay); + } + } + + void PlayerOutput::DisplayEndScreen(void) + { + gameWindow.clear(); + sf::Vector2f textPosition(gameBoundaries); + textPosition.x = textPosition.x / 2; + textPosition.y = textPosition.y / 2; + sf::Font font; + font.loadFromFile("Arial.ttf"); + sf::Text gameOverText("Game Over", font); + gameOverText.setPosition(textPosition); + gameWindow.draw(gameOverText); + gameWindow.display(); + return; + } + + void PlayerOutput::DisplayGameState(std::vector< std::vector >& gameBoard) + { + CheckWindowEvents(); + sf::Vector2f location; + char* letterOnBoard; + for (float y = 0; y < gameBoundaries.y; y++) + { + for (float x = 0; x < gameBoundaries.x; x++) + { + location.x = x; + location.y = y; + letterOnBoard = &gameBoard.at(location.y).at(location.x); + switch (*letterOnBoard) + { + case 'O': + DrawSnake(location); + break; + case 'X': + DrawFood(location); + break; + default: + DrawEmpty(location); + break; + } + } + } + gameWindow.display(); + sf::sleep(delay); + return; + } + + void PlayerOutput::StartGameWindow(void) + { + gameWindow.create(gameVideoSettings, "SnakePlusPlus"); + isWindowAlive = true; + return; + } + + void PlayerOutput::CheckWindowEvents(void) + { + sf::Event event; + while (gameWindow.pollEvent(event)) + { + if ((event.type == sf::Event::Closed) || + (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))) + gameWindow.close(); + } + } + + void PlayerOutput::DrawEmpty(sf::Vector2f location) + { + location *= static_cast(kGridSize); + drawObject.setPosition(location); + drawObject.setFillColor(sf::Color::Black); + gameWindow.draw(drawObject); + return; + } + + void PlayerOutput::DrawFood(sf::Vector2f location) + { + location *= static_cast(kGridSize); + drawObject.setPosition(location); + drawObject.setFillColor(sf::Color::Red); + gameWindow.draw(drawObject); + return; + } + + void PlayerOutput::DrawSnake(sf::Vector2f location) + { + location *= static_cast(kGridSize); + drawObject.setPosition(location); + drawObject.setFillColor(sf::Color::Green); + gameWindow.draw(drawObject); + return; + } +} diff --git a/src/playerinterface.hpp b/src/playerinterface.hpp new file mode 100755 index 0000000..f4267ca --- /dev/null +++ b/src/playerinterface.hpp @@ -0,0 +1,43 @@ +#ifndef PLAYERINTERFACE_HPP +#define PLAYERINTERFACE_HPP + +#include "common.hpp" +#include + +const int kGridSize = 25; + +namespace snakeplusplus +{ + class PlayerInput + { + public: + PlayerInput(void); + PlayerDirection GetPlayerInput(void); + private: + PlayerDirection lastPlayerInput; + }; + + class PlayerOutput + { + public: + sf::Vector2f gameBoundaries; + PlayerOutput(void); + bool IsOpen(void); + void CheckContinue(void); + void DisplayGameState(std::vector< std::vector >& gameBoard); + void StartGameWindow(void); + private: + void CheckWindowEvents(void); + void DisplayEndScreen(void); + void DrawEmpty(sf::Vector2f location); + void DrawFood(sf::Vector2f location); + void DrawSnake(sf::Vector2f location); + sf::RenderWindow gameWindow; + sf::VideoMode gameVideoSettings; + sf::RectangleShape drawObject; + bool isWindowAlive; + sf::Time delay = sf::milliseconds(60); + }; +} + +#endif diff --git a/src/snake.cpp b/src/snake.cpp new file mode 100755 index 0000000..8de60c0 --- /dev/null +++ b/src/snake.cpp @@ -0,0 +1,37 @@ +// Snake.cpp +#include +#include +#include +#include +#include +#include "snake.hpp" + +namespace snakeplusplus +{ + void Snake::Pop(void) + { + *(body.front()) = ' '; + body.pop(); + } + + Food::Food(void) + { + generator.seed(std::random_device{}()); + } + + // Returns a new food object for the snakeFood + void Food::GenerateNewFood(sf::Vector2f boundaries) + { + location.x = GenerateRandomNumber(boundaries.x); + location.y = GenerateRandomNumber(boundaries.y); + } + + // Returns a newly generated number + int Food::GenerateRandomNumber(int generationLimit) + { + int generatedNumber; + std::uniform_int_distribution<> distribution(0, generationLimit - 1); + generatedNumber = distribution(generator); + return generatedNumber; + } +} diff --git a/src/snake.hpp b/src/snake.hpp new file mode 100755 index 0000000..3ed81ea --- /dev/null +++ b/src/snake.hpp @@ -0,0 +1,35 @@ +// Snake.h +#ifndef SNAKE_HPP +#define SNAKE_HPP + +#include +#include +#include +#include +#include + +namespace snakeplusplus +{ + struct Snake + { + public: + sf::Vector2f headLocation; + sf::Vector2f speed; + std::queue body; + void Pop(void); + }; + + struct Food + { + public: + Food(void); + sf::Vector2f location; + char* food; + void GenerateNewFood(sf::Vector2f boundaries); + private: + std::default_random_engine generator; + int GenerateRandomNumber(int generationLimit); + }; +} + +#endif