Merge pull request #20 from Trimutex/development

Update to current progress
This commit is contained in:
Gregory 2023-08-19 00:09:12 -05:00 committed by GitHub
commit 2969fd89db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 111 additions and 99 deletions

View File

@ -5,6 +5,7 @@ add_executable(snakeplusplus
./gamestate.cpp
./snake.cpp
./playerinterface.cpp
./common.cpp
)
target_include_directories(snakeplusplus PUBLIC ${CMAKE_CURRENT_LIST_DIR})

21
src/common.cpp Executable file
View File

@ -0,0 +1,21 @@
// common.cpp
#include <random>
#include "common.hpp"
namespace snakeplusplus
{
std::default_random_engine generator;
void InitializeGenerator(void)
{
generator.seed(std::random_device{}());
}
// Returns a newly generated number
int GenerateRandomNumber(int generationLimit)
{
int generatedNumber;
std::uniform_int_distribution<> distribution(0, generationLimit - 1);
generatedNumber = distribution(snakeplusplus::generator);
return generatedNumber;
}
}

View File

@ -1,13 +1,20 @@
#ifndef COMMON_HPP
#define COMMON_HPP
enum PlayerDirection
namespace snakeplusplus
{
kNone = 0,
kLeft = 1,
kUp = 2,
kDown = 3,
kRight = 4
};
void InitializeGenerator(void);
int GenerateRandomNumber(int generationLimit);
enum PlayerDirection
{
kNone = 0,
kLeft = 1,
kUp = 2,
kDown = 3,
kRight = 4
};
}
#endif

View File

@ -1,9 +1,7 @@
// GameState.cpp
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <SFML/Graphics.hpp>
#include <tuple>
#include "common.hpp"
#include "playerinterface.hpp"
#include "gamestate.hpp"
@ -12,27 +10,32 @@ namespace snakeplusplus
{
GameEngine::GameEngine()
{
snakeplusplus::InitializeGenerator();
return;
}
void GameEngine::StartGame()
void GameEngine::Start()
{
//ApplySettings();
PrepareGameBoard();
graphics.StartGameWindow();
GameLoop();
Loop();
return;
}
void GameEngine::GameLoop(void)
void GameEngine::Reset()
{
graphics.CheckContinue();
player.Reset();
PrepareGameBoard();
isGameOver = 0;
return;
}
void GameEngine::Loop(void)
{
while (graphics.IsOpen())
{
if (isGameOver)
{
graphics.CheckContinue();
isGameOver = 0;
}
if (isGameOver) {Reset();}
UpdatePlayerSpeed();
PlaceNewSnakePart(MovePlayer());
RegenerateFood();
@ -56,11 +59,12 @@ namespace snakeplusplus
void GameEngine::PlaceNewSnakePart(sf::Vector2f location)
{
if (!player.speed.x && !player.speed.y) { return; }
try
{
char* locationState;
locationState = &gameBoard.at(location.y).at(location.x);
if (*locationState == 'O' && player.body.size() > 1)
if (*locationState == 'O' && (player.body.size() > 1))
isGameOver = true; // Game should end (Snake touching snake)
*locationState = 'O';
player.body.push(locationState);
@ -69,8 +73,8 @@ namespace snakeplusplus
player.Pop();
} catch (const std::out_of_range& error) {
isGameOver = true; // Snake ran into edge
exit(0);
}
return;
}
// Generates new food until not colliding with player
@ -78,7 +82,6 @@ namespace snakeplusplus
{
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;
@ -95,22 +98,26 @@ namespace snakeplusplus
gameBoard.clear();
sf::Vector2f boardDimensions = GetGameBoundaries();
gameBoard.resize(boardDimensions.y, std::vector<char> (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';
// Snake setup
{
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';
}
return;
}
void GameEngine::UpdatePlayerSpeed(void)
{
PlayerDirection input = controls.GetPlayerInput();
switch (input) {
switch (GetPlayerInput()) {
case kUp:
player.speed.x = 0;
player.speed.y = -1;
@ -130,5 +137,6 @@ namespace snakeplusplus
default:
break;
}
return;
}
}

View File

@ -2,7 +2,6 @@
#ifndef GAMESTATE_HPP
#define GAMESTATE_HPP
#include <memory>
#include <SFML/Graphics.hpp>
#include "snake.hpp"
#include "playerinterface.hpp"
@ -13,18 +12,17 @@ namespace snakeplusplus
{
public:
GameEngine();
void StartGame(void);
void Start(void);
void Reset(void);
sf::Vector2f GetGameBoundaries(void);
private:
std::vector< std::vector<char> > gameBoard;
PlayerInput controls;
PlayerOutput graphics;
Snake player;
Food playerFood;
bool useSFML = 1;
bool isGameOver = 0;
void DisplayEndScreen(void);
void GameLoop(void);
void Loop(void);
sf::Vector2f MovePlayer(void);
void PlaceNewSnakePart(sf::Vector2f location);
void RegenerateFood(void);

View File

@ -3,5 +3,6 @@
int main(void)
{
snakeplusplus::GameEngine game;
game.StartGame();
game.Start();
return 0;
}

View File

@ -1,26 +1,24 @@
#include "playerinterface.hpp"
#include <SFML/System/Vector2.hpp>
#include <cstdlib>
#include <iostream>
#include <SFML/Window/Keyboard.hpp>
namespace snakeplusplus
{
PlayerInput::PlayerInput(void)
PlayerDirection GetPlayerInput(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;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)
|| sf::Keyboard::isKeyPressed(sf::Keyboard::A))
return kLeft;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)
|| sf::Keyboard::isKeyPressed(sf::Keyboard::W))
return kUp;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)
|| sf::Keyboard::isKeyPressed(sf::Keyboard::S))
return kDown;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)
|| sf::Keyboard::isKeyPressed(sf::Keyboard::D))
return kRight;
return kNone;
}
bool PlayerOutput::IsOpen(void)
@ -47,8 +45,8 @@ namespace snakeplusplus
while (true)
{
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();
return;
@ -66,7 +64,7 @@ namespace snakeplusplus
textPosition.y = textPosition.y / 2;
sf::Font font;
font.loadFromFile("Arial.ttf");
sf::Text gameOverText("Game Over", font);
sf::Text gameOverText("Game Over\nPress 'Enter' to play again", font);
gameOverText.setPosition(textPosition);
gameWindow.draw(gameOverText);
gameWindow.display();
@ -76,25 +74,22 @@ namespace snakeplusplus
void PlayerOutput::DisplayGameState(std::vector< std::vector<char> >& 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);
letterOnBoard = &gameBoard.at(y).at(x);
switch (*letterOnBoard)
{
case 'O':
DrawSnake(location);
DrawSnake(sf::Vector2f(x, y));
break;
case 'X':
DrawFood(location);
DrawFood(sf::Vector2f(x,y));
break;
default:
DrawEmpty(location);
DrawEmpty(sf::Vector2f(x,y));
break;
}
}
@ -116,8 +111,8 @@ namespace snakeplusplus
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();
}
}

View File

@ -8,14 +8,7 @@ const int kGridSize = 25;
namespace snakeplusplus
{
class PlayerInput
{
public:
PlayerInput(void);
PlayerDirection GetPlayerInput(void);
private:
PlayerDirection lastPlayerInput;
};
PlayerDirection GetPlayerInput(void);
class PlayerOutput
{

View File

@ -1,9 +1,7 @@
// Snake.cpp
#include <algorithm>
#include <memory>
#include <queue>
#include <random>
#include <SFML/Graphics.hpp>
#include "common.hpp"
#include "snake.hpp"
namespace snakeplusplus
@ -12,26 +10,22 @@ namespace snakeplusplus
{
*(body.front()) = ' ';
body.pop();
return;
}
Food::Food(void)
void Snake::Reset(void)
{
generator.seed(std::random_device{}());
while (!body.empty()) Pop();
speed.x = 0;
speed.y = 0;
return;
}
// 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;
location.x = snakeplusplus::GenerateRandomNumber(boundaries.x);
location.y = snakeplusplus::GenerateRandomNumber(boundaries.y);
return;
}
}

View File

@ -3,10 +3,7 @@
#define SNAKE_HPP
#include <SFML/System/Vector2.hpp>
#include <memory>
#include <queue>
#include <random>
#include <SFML/Graphics.hpp>
namespace snakeplusplus
{
@ -17,18 +14,15 @@ namespace snakeplusplus
sf::Vector2f speed;
std::queue<char*> body;
void Pop(void);
void Reset(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);
};
}