diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 04900db..147c92d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ add_executable(snakeplusplus ./snake.cpp ./playerinterface.cpp ./common.cpp + ./botinterface.cpp ) target_include_directories(snakeplusplus PUBLIC ${CMAKE_CURRENT_LIST_DIR}) diff --git a/src/botinterface.cpp b/src/botinterface.cpp new file mode 100755 index 0000000..6b4ed21 --- /dev/null +++ b/src/botinterface.cpp @@ -0,0 +1,26 @@ +#include "botinterface.hpp" +#include "common.hpp" +#include + +namespace snakeplusplus +{ + PlayerDirection lastKnownDirection = kNone; + PlayerDirection GetBotInput(const sf::Vector2f* snakeHeadLocation, const sf::Vector2f* foodLocation) + { + sf::Vector2f directionDelta; + directionDelta = *snakeHeadLocation - *foodLocation; + if ((directionDelta.y > 0) + && (lastKnownDirection != kDown)) + { lastKnownDirection = kUp; } + else if ((directionDelta.y < 0) + && (lastKnownDirection != kUp)) + { lastKnownDirection = kDown; } + else if ((directionDelta.x > 0) + && (lastKnownDirection != kRight)) + { lastKnownDirection = kLeft; } + else if ((directionDelta.x < 0) + && (lastKnownDirection != kLeft)) + { lastKnownDirection = kRight; } + return lastKnownDirection; + } +} diff --git a/src/botinterface.hpp b/src/botinterface.hpp new file mode 100755 index 0000000..3f98ab7 --- /dev/null +++ b/src/botinterface.hpp @@ -0,0 +1,12 @@ +#ifndef BOTINTERFACE_HPP +#define BOTINTERFACE_HPP + +#include "common.hpp" +#include + +namespace snakeplusplus +{ + PlayerDirection GetBotInput(const sf::Vector2f* snakeHeadLocation, const sf::Vector2f* foodLocation); +} + +#endif diff --git a/src/gamestate.cpp b/src/gamestate.cpp index 67941f4..af3899d 100755 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -1,7 +1,7 @@ // GameState.cpp #include #include -#include +#include "botinterface.hpp" #include "common.hpp" #include "playerinterface.hpp" #include "gamestate.hpp" @@ -10,7 +10,7 @@ namespace snakeplusplus { GameEngine::GameEngine() { - snakeplusplus::InitializeGenerator(); + InitializeGenerator(); return; } @@ -24,10 +24,10 @@ namespace snakeplusplus void GameEngine::Reset() { - graphics.CheckContinue(); + graphics.CheckContinue(isBotControlled); player.Reset(); PrepareGameBoard(); - isGameOver = 0; + isGameOver = false; return; } @@ -35,7 +35,7 @@ namespace snakeplusplus { while (graphics.IsOpen()) { - if (isGameOver) {Reset();} + if (isGameOver) { Reset(); } UpdatePlayerSpeed(); PlaceNewSnakePart(MovePlayer()); RegenerateFood(); @@ -88,8 +88,7 @@ namespace snakeplusplus playerFood.GenerateNewFood(GetGameBoundaries()); newLocation = playerFood.location; } - if (isUpdated) - gameBoard.at(newLocation.y).at(newLocation.x) = 'X'; + if (isUpdated) { gameBoard.at(newLocation.y).at(newLocation.x) = 'X'; } return; } @@ -99,40 +98,44 @@ namespace snakeplusplus sf::Vector2f boardDimensions = GetGameBoundaries(); gameBoard.resize(boardDimensions.y, std::vector (boardDimensions.x, ' ')); // Snake setup + player.headLocation.x = GenerateRandomNumber(boardDimensions.x); + player.headLocation.y = GenerateRandomNumber(boardDimensions.y); { - player.headLocation.x = GenerateRandomNumber(boardDimensions.x); - player.headLocation.y = GenerateRandomNumber(boardDimensions.y); char* locationState = &gameBoard.at(player.headLocation.y).at(player.headLocation.x); player.body.push(locationState); *locationState = 'O'; } // Food setup - { - playerFood.GenerateNewFood(boardDimensions); - sf::Vector2f newLocation = playerFood.location; - gameBoard.at(newLocation.y).at(newLocation.x) = 'X'; - } + playerFood.GenerateNewFood(boardDimensions); + gameBoard.at(playerFood.location.y).at(playerFood.location.x) = 'X'; return; } void GameEngine::UpdatePlayerSpeed(void) { - switch (GetPlayerInput()) { + PlayerDirection controller; + if (isBotControlled) { controller = GetBotInput(&player.headLocation, &playerFood.location); } + else { controller = GetPlayerInput(); } + switch (controller) { case kUp: + if (player.speed.y == kUnitSpeed) { break; } player.speed.x = 0; - player.speed.y = -1; + player.speed.y = -kUnitSpeed; break; case kLeft: - player.speed.x = -1; + if (player.speed.x == kUnitSpeed) { break; } + player.speed.x = -kUnitSpeed; player.speed.y = 0; break; case kRight: - player.speed.x = 1; + if (player.speed.x == -kUnitSpeed) { break; } + player.speed.x = kUnitSpeed; player.speed.y = 0; break; case kDown: + if (player.speed.y == -kUnitSpeed) { break; } player.speed.x = 0; - player.speed.y = 1; + player.speed.y = kUnitSpeed; break; default: break; diff --git a/src/gamestate.hpp b/src/gamestate.hpp index 29763a4..7665477 100755 --- a/src/gamestate.hpp +++ b/src/gamestate.hpp @@ -8,6 +8,8 @@ namespace snakeplusplus { + const int kUnitSpeed = 1; + class GameEngine { public: @@ -21,6 +23,7 @@ namespace snakeplusplus Snake player; Food playerFood; bool isGameOver = 0; + bool isBotControlled = 1; void DisplayEndScreen(void); void Loop(void); sf::Vector2f MovePlayer(void); diff --git a/src/playerinterface.cpp b/src/playerinterface.cpp index d63706c..ac01982 100755 --- a/src/playerinterface.cpp +++ b/src/playerinterface.cpp @@ -38,9 +38,9 @@ namespace snakeplusplus return; } - void PlayerOutput::CheckContinue(void) + void PlayerOutput::CheckContinue(bool isBotControlled) { - sf::Event event; + if (isBotControlled) { return; } DisplayEndScreen(); while (true) { @@ -108,7 +108,6 @@ namespace snakeplusplus void PlayerOutput::CheckWindowEvents(void) { - sf::Event event; while (gameWindow.pollEvent(event)) { if ((event.type == sf::Event::Closed) diff --git a/src/playerinterface.hpp b/src/playerinterface.hpp index 26e12f5..f397a14 100755 --- a/src/playerinterface.hpp +++ b/src/playerinterface.hpp @@ -16,7 +16,7 @@ namespace snakeplusplus sf::Vector2f gameBoundaries; PlayerOutput(void); bool IsOpen(void); - void CheckContinue(void); + void CheckContinue(bool isBotControlled); void DisplayGameState(std::vector< std::vector >& gameBoard); void StartGameWindow(void); private: @@ -28,8 +28,9 @@ namespace snakeplusplus sf::RenderWindow gameWindow; sf::VideoMode gameVideoSettings; sf::RectangleShape drawObject; + sf::Event event; bool isWindowAlive; - sf::Time delay = sf::milliseconds(60); + sf::Time delay = sf::milliseconds(50); }; } diff --git a/src/snake.cpp b/src/snake.cpp index 4dfc7f4..c9602a5 100755 --- a/src/snake.cpp +++ b/src/snake.cpp @@ -24,8 +24,8 @@ namespace snakeplusplus // Returns a new food object for the snakeFood void Food::GenerateNewFood(sf::Vector2f boundaries) { - location.x = snakeplusplus::GenerateRandomNumber(boundaries.x); - location.y = snakeplusplus::GenerateRandomNumber(boundaries.y); + location.x = GenerateRandomNumber(boundaries.x); + location.y = GenerateRandomNumber(boundaries.y); return; } }