snakeplusplus/src/gamestate.cpp

191 lines
5.1 KiB
C++
Raw Normal View History

// GameState.cpp
#include <stdexcept>
#include <SFML/Graphics.hpp>
#include "botinterface.hpp"
#include "common.hpp"
#include "playerinterface.hpp"
#include "gamestate.hpp"
GameEngine::GameEngine()
{
InitializeGenerator();
return;
}
2023-03-17 20:13:50 -05:00
void GameEngine::Start()
{
PrepareGameBoard();
if (!state.m_bNoDisplay)
graphics.StartGameWindow();
Loop();
return;
}
2023-03-12 08:50:50 -05:00
void GameEngine::Reset()
{
if (!state.m_bIsBotControlled)
graphics.CheckContinue();
2024-08-03 21:18:57 -05:00
else
bot.AddIteration(player.body.size());
player.Reset();
PrepareGameBoard();
state.m_bIsGameOver = false;
if (state.m_bIsBotControlled) {
if (!state.m_bSmart) {
while (!bot.path.empty())
bot.path.pop();
}
if (state.m_bNoDisplay)
graphics.SetShowGame(false);
if (state.m_bSkipIterations)
graphics.SetShowGame((bot.amountPlayed + 1) % 50 == 0);
graphics.SetShowGame(true);
}
}
void GameEngine::Loop(void)
{
int currentScore = 0;
while (graphics.IsOpen() || state.m_bNoDisplay)
{
if (state.m_bIsGameOver) { Reset(); }
UpdatePlayerSpeed();
PlaceNewSnakePart(MovePlayer());
RegenerateFood();
currentScore = player.body.size() * 100;
if (!state.m_bNoDisplay)
graphics.DisplayGameState(gameBoard, currentScore);
}
return;
}
sf::Vector2f GameEngine::MovePlayer(void)
{
return sf::Vector2f(player.headLocation.x + player.speed.x, player.headLocation.y + player.speed.y);
}
sf::Vector2f GameEngine::GetGameBoundaries(void)
{
return graphics.gameBoundaries;
}
PlayerDirection GameEngine::GetCurrentDirection(void) {
if (player.speed.x) {
if (player.speed.x > 0)
return kRight;
else
return kLeft;
} else {
if (player.speed.y > 0)
return kDown;
else
return kUp;
}
}
int GameEngine::GetPlayerSize(void) {
return player.body.size();
}
sf::Vector2f GameEngine::GetHeadLocation(void) {
return player.headLocation;
}
sf::Vector2f GameEngine::GetFoodLocation(void) {
return playerFood.location;
}
void GameEngine::PlaceNewSnakePart(sf::Vector2f location) {
if (!player.speed.x && !player.speed.y) { return; }
try {
GameSpace* locationState = &gameBoard.at(location.y).at(location.x);
if (locationState->m_bSnake && (player.body.size() > 1)) {
state.m_bIsGameOver = true; // Game should end (Snake touching snake)
}
locationState->m_bSnake = true;
player.body.push(locationState);
player.headLocation = location;
if (playerFood.location != location)
player.Pop();
else {
locationState->m_bFood = false;
if (state.m_bIsBotControlled)
bot.ResetPath();
}
} catch (const std::out_of_range& error) {
state.m_bIsGameOver = true; // Snake ran into edge
}
return;
}
// Generates new food until not colliding with player
void GameEngine::RegenerateFood()
{
// Generate a new food location if the current one is occupied
while (gameBoard.at(playerFood.location.y).at(playerFood.location.x).m_bSnake) {
playerFood.GenerateNewFood(GetGameBoundaries());
}
// Update the game board with the new food location
gameBoard.at(playerFood.location.y).at(playerFood.location.x).m_bFood = 1;
}
void GameEngine::PrepareGameBoard(void)
{
gameBoard.clear();
sf::Vector2f boardDimensions = GetGameBoundaries();
gameBoard.resize(boardDimensions.y, std::vector<GameSpace>(boardDimensions.x));
// Snake setup
player.headLocation.x = GenerateRandomNumber(boardDimensions.x);
player.headLocation.y = GenerateRandomNumber(boardDimensions.y);
{
GameSpace* locationState = &gameBoard.at(player.headLocation.y).at(player.headLocation.x);
player.body.push(locationState);
locationState->m_bSnake = true;
}
// Food setup
playerFood.GenerateNewFood(boardDimensions);
gameBoard.at(playerFood.location.y).at(playerFood.location.x).m_bFood = true;
return;
}
void GameEngine::UpdatePlayerSpeed(void)
{
PlayerDirection controller;
if (state.m_bIsBotControlled) {
if (bot.path.empty()) {
2024-08-03 20:42:34 -05:00
bot.GetNewPath(player.headLocation);
}
controller = bot.GetInput(&player.headLocation);
}
else { controller = GetPlayerInput(); }
switch (controller) {
case kUp:
if (player.speed.y == kUnitSpeed) { break; }
player.speed.x = 0;
player.speed.y = -kUnitSpeed;
break;
case kLeft:
if (player.speed.x == kUnitSpeed) { break; }
player.speed.x = -kUnitSpeed;
player.speed.y = 0;
break;
case kRight:
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 = kUnitSpeed;
break;
default:
break;
}
return;
}