diff --git a/Config/game-config.txt b/Config/game-config.txt new file mode 100644 index 0000000..1351ef4 --- /dev/null +++ b/Config/game-config.txt @@ -0,0 +1,27 @@ +framerate 60 + +playerStartPos 700 700 + +playerSize 500 10 + +playerSpeed 10 + +playerColor 1 1 1 + +ballRadius 5 + +ballSpeed 2.5 + +ballColor 1 0 0 + +brickSize 50 10 + +brickColor 1 1 1 + +specialBrickColor 0 1 0 + +bricksPerRow 8 + +bricksPerColumn 5 + +specialBrickCount 3 diff --git a/include/Color.h b/include/Color.h new file mode 100644 index 0000000..fa80187 --- /dev/null +++ b/include/Color.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +struct Color +{ + Color() = default; + Color(float r_in, float g_in, float b_in, float a_in); + + Color(sf::Color color_in); + + sf::Color sfml(); + + float* imgui(); + + float r{}; + float g{}; + float b{}; + float a{1.f}; +}; \ No newline at end of file diff --git a/include/Game.h b/include/Game.h index 2835a15..91b8571 100644 --- a/include/Game.h +++ b/include/Game.h @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -15,8 +14,8 @@ struct Ball Ball(sf::Vector2f position_in, sf::Vector2f vel_in); sf::Vector2f pos; - sf::Vector2f previousPos{}; sf::Vector2f velocity; + sf::Vector2f previousPos{}; bool alive{true}; }; @@ -47,6 +46,7 @@ public: Game(); void run(); + void runNoImgui(); private: void imgui(); @@ -65,6 +65,10 @@ private: void checkBallCollision(); + void resetGame(); + + bool parseConfigFile(); + private: sf::Clock clock; @@ -79,23 +83,23 @@ private: sf::RectangleShape tempRect; // mostly used for imgui - sf::Vector2f brickSize{50, 10}; - sf::Vector2f playerSize{500, 10}; - sf::Vector2f playerStartPos{700,700}; - sf::Vector2f brickHalfSize{brickSize / 2.f}; - sf::Vector2f playerHalfSize{playerSize / 2.f}; - int rowSize{8}; - int columnSize{5}; - int totalSpecialBricks{3}; + sf::Vector2f brickSize{}; + sf::Vector2f playerSize{}; + sf::Vector2f playerStartPos{}; + sf::Vector2f brickHalfSize{}; + sf::Vector2f playerHalfSize{}; + int rowSize{}; + int columnSize{}; + int totalSpecialBricks{}; int totalBricks{rowSize * columnSize}; - unsigned int frameRate{60}; - float playerSpeed{10}; - float ballRadius{5.0f}; - float ballMaxSpeed{10}; - Color ballColor{sf::Color::Red}; - Color brickColor{sf::Color::White}; - Color playerColor{sf::Color::White}; - Color specialBrickColor{sf::Color::Blue}; + unsigned int framerate{}; + float playerSpeed{}; + float ballRadius{}; + float ballMaxSpeed{}; + Color ballColor{}; + Color brickColor{}; + Color playerColor{}; + Color specialBrickColor{}; bool windowCollasped{false}; static constexpr unsigned int numPhysicsUpdates{4}; }; \ No newline at end of file diff --git a/include/Physics.h b/include/Physics.h new file mode 100644 index 0000000..e4fe247 --- /dev/null +++ b/include/Physics.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +sf::Vector2f getOverlap(sf::FloatRect first, sf::FloatRect second); +sf::Vector2f velocityInRandomDir(float speed_in); +sf::Vector2f velocityInDirection(float speed_in, sf::Angle angle_in); \ No newline at end of file diff --git a/include/Util.h b/include/Util.h index 2d6a381..bfe3fc1 100644 --- a/include/Util.h +++ b/include/Util.h @@ -1,40 +1,5 @@ #pragma once -#include - -struct Color -{ - Color() = default; - Color(float r_in, float g_in, float b_in, float a_in = 1.0f) - : r(r_in) - , g(g_in) - , b(b_in) - , a(a_in) - { } - - Color(sf::Color color_in) - : r((float)color_in.r / 255.f) - , g((float)color_in.g / 255.f) - , b((float)color_in.b / 255.f) - , a((float)color_in.a / 255.f) - { } - - float r{}; - float g{}; - float b{}; - float a{}; - - sf::Color sfml() - { - return sf::Color{uint8_t(r * 255), uint8_t(g * 255), uint8_t(b * 255), uint8_t(a * 255)}; - } - - float* imgui() - { - return &r; - } -}; - -sf::Vector2f getOverlap(sf::FloatRect first, sf::FloatRect second); -sf::Vector2f velocityInRandomDir(float speed_in); -sf::Vector2f velocityInDirection(float speed_in, sf::Angle angle_in); \ No newline at end of file +#include +#include +#include \ No newline at end of file diff --git a/src/Color.cpp b/src/Color.cpp new file mode 100644 index 0000000..09a461e --- /dev/null +++ b/src/Color.cpp @@ -0,0 +1,27 @@ +#include + +#include + +Color::Color(float r_in, float g_in, float b_in, float a_in = 1.0f) + : r(r_in) + , g(g_in) + , b(b_in) + , a(a_in) +{ } + +Color::Color(sf::Color color_in) + : r(color_in.r / 255.f) + , g(color_in.g / 255.f) + , b(color_in.b / 255.f) + , a(color_in.a / 255.f) +{ } + +sf::Color Color::sfml() +{ + return sf::Color{uint8_t(r * 255), uint8_t(g * 255), uint8_t(b * 255), uint8_t(a * 255)}; +} + +float* Color::imgui() +{ + return &r; +} diff --git a/src/Game.cpp b/src/Game.cpp index f7bc6af..9ad33c0 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -2,18 +2,18 @@ #include #include -#include #include #include #include #include +#include #include Ball::Ball(sf::Vector2f position_in, sf::Vector2f vel_in) - : velocity(vel_in) - , pos(position_in) + : pos(position_in) + , velocity(vel_in) { } Brick::Brick(sf::Vector2f position_in) @@ -28,13 +28,19 @@ Player::Player(sf::Vector2f position_in) Game::Game() : window({sf::VideoMode({ 1920u, 1080u }), "breakout"}) { - window.setFramerateLimit(frameRate); - + if (!ImGui::SFML::Init(window)) return; + + if (!parseConfigFile()) return; + + window.setFramerateLimit(framerate); player.pos = playerStartPos; + playerHalfSize = playerSize / 2.f; + brickHalfSize = brickSize / 2.f; tempCircle.setOrigin({ballRadius, ballRadius}); + ballMaxSpeed /= numPhysicsUpdates; bricks.reserve(totalBricks); bricks.emplace_back(sf::Vector2f{200, 100}); @@ -45,6 +51,65 @@ Game::Game() ballsToAdd.emplace_back(playerStartPos.x, playerStartPos.y - 300); } +bool Game::parseConfigFile() +{ + std::ifstream configFile{"Config/game-config.txt"}; + + if(!configFile) + { + std::cerr << "ERROR: CANNOT OPEN 'game-config.txt'\n"; + return false; + } + + std::string inputBuff; + while(configFile >> inputBuff) + { + if (inputBuff == "framerate") + configFile >> framerate; + + if (inputBuff == "bricksPerRow") + configFile >> rowSize; + + if (inputBuff == "ballRadius") + configFile >> ballRadius; + + if (inputBuff == "playerSpeed") + configFile >> playerSpeed; + + if (inputBuff == "bricksPerColumn") + configFile >> columnSize; + + if (inputBuff == "specialBrickCount") + configFile >> totalSpecialBricks; + + if (inputBuff == "brickSize") + configFile >> brickSize.x >> brickSize.y; + + if (inputBuff == "playerSize") + configFile >> playerSize.x >> playerSize.y; + + if (inputBuff == "ballColor") + configFile >> ballColor.r >> ballColor.g >> ballColor.b; + + if (inputBuff == "playerStartPos") + configFile >> playerStartPos.x >> playerStartPos.y; + + if (inputBuff == "brickColor") + configFile >> brickColor.r >> brickColor.g >> brickColor.b; + + if (inputBuff == "playerColor") + configFile >> playerColor.r >> playerColor.g >> playerColor.b; + + if (inputBuff == "specialBrickColor") + configFile >> specialBrickColor.r >> specialBrickColor.g >> specialBrickColor.b; + + if (inputBuff == "ballSpeed") + configFile >> ballMaxSpeed; + } + + return true; +} + void Game::input() { while (const std::optional event = window.pollEvent()) @@ -77,6 +142,10 @@ void Game::input() case sf::Keyboard::Scan::F1: windowCollasped = !windowCollasped; break; + + case sf::Keyboard::Scan::R: + resetGame(); + break; default: break; @@ -106,11 +175,12 @@ void Game::input() { switch (MouseButtonPressed->button) { - case sf::Mouse::Button::Left: - specialBricks.emplace_back((sf::Vector2f)MouseButtonPressed->position); - break; - default: - break; + case sf::Mouse::Button::Left: + specialBricks.emplace_back((sf::Vector2f)MouseButtonPressed->position); + break; + + default: + break; } } @@ -145,8 +215,8 @@ void Game::checkBallCollision() for (auto& brick : bricks) { const sf::FloatRect brickBounds = {brick.pos, brickHalfSize}; - auto intersect = getOverlap(ballBounds, brickBounds); - auto previousIntersect = getOverlap(previousBallBounds, brickBounds); + const auto intersect = getOverlap(ballBounds, brickBounds); + const auto previousIntersect = getOverlap(previousBallBounds, brickBounds); if (intersect.x > 0 && previousIntersect.x <= 0 && intersect.y > 0) { @@ -252,8 +322,8 @@ void Game::checkBallCollision() const sf:: FloatRect playerBounds = {player.pos, playerHalfSize}; const sf:: FloatRect previousPlayerBounds = {player.previousPos, playerHalfSize}; - auto intersect = getOverlap(ballBounds, playerBounds); - auto previousIntersect = getOverlap(previousBallBounds, previousPlayerBounds); + const auto intersect = getOverlap(ballBounds, playerBounds); + const auto previousIntersect = getOverlap(previousBallBounds, previousPlayerBounds); // coming from x direction if (intersect.x > 0 && previousIntersect.x <= 0 && intersect.y > 0) @@ -294,9 +364,9 @@ void Game::updateEntities() const auto limit = ballsToAdd.size(); - for (int i = 0; i < limit; i++) + for (size_t i = 0; i < limit; i++) { - balls.emplace_back(ballsToAdd[i], velocityInRandomDir(ballMaxSpeed / numPhysicsUpdates)); + balls.emplace_back(ballsToAdd[i], velocityInRandomDir(ballMaxSpeed)); ballsToAdd[i] = {0,0}; } @@ -326,7 +396,7 @@ void Game::movement() ball.pos += ball.velocity; } - int dir = player.right - player.left; + const int dir = player.right - player.left; player.previousPos = player.pos; player.pos.x += (playerSpeed / numPhysicsUpdates) * dir; @@ -334,7 +404,6 @@ void Game::movement() void Game::imgui() { - ImGui::SFML::Update(window, clock.restart()); ImGui::Begin("menu"); ImGui::SetWindowCollapsed(windowCollasped); @@ -356,7 +425,7 @@ void Game::imgui() ImGui::ColorEdit3("Player Color", playerColor.imgui()); ImGui::ColorEdit3("Ball Color", ballColor.imgui()); ImGui::ColorEdit3("Brick Color", brickColor.imgui()); - ImGui::ColorEdit3("Special Brick Color", specialBrickColor.imgui()); + ImGui::ColorEdit3("Special Brick Color", specialBrickColor.imgui()); ImGui::End(); } @@ -400,13 +469,24 @@ void Game::render() window.display(); } +void Game::resetGame() +{ + bricks.clear(); + specialBricks.clear(); + balls.clear(); + ballsToAdd.clear(); + +} + void Game::run() { while(window.isOpen()) { + ImGui::SFML::Update(window, clock.restart()); + input(); - for (int i = 0; i <= numPhysicsUpdates; i++) + for (size_t i = 0; i <= numPhysicsUpdates; i++) { updateEntities(); @@ -424,3 +504,27 @@ void Game::run() ImGui::SFML::Shutdown(); } + +void Game::runNoImgui() +{ + while(window.isOpen()) + { + ImGui::SFML::Update(window, clock.restart()); + input(); + + for (size_t i = 0; i <= numPhysicsUpdates; i++) + { + updateEntities(); + + movement(); + + collision(); + } + + checkEndGame(); + + render(); + } + + ImGui::SFML::Shutdown(); +} \ No newline at end of file diff --git a/src/Util.cpp b/src/Physics.cpp similarity index 83% rename from src/Util.cpp rename to src/Physics.cpp index 4b41147..6db40ee 100644 --- a/src/Util.cpp +++ b/src/Physics.cpp @@ -1,4 +1,7 @@ -#include +#include + +#include + #include sf::Vector2f getOverlap(sf::FloatRect first, sf::FloatRect second) @@ -13,7 +16,7 @@ sf::Vector2f getOverlap(sf::FloatRect first, sf::FloatRect second) return result; } -sf::Vector2f velocityInRandomDir(float speed_in) +sf::Vector2f velocityInRandomDir(const float speed_in) { const bool upOrDown{(bool)Random::get(0,1)}; @@ -29,7 +32,7 @@ sf::Vector2f velocityInRandomDir(float speed_in) } // used for debugging -sf::Vector2f velocityInDirection(float speed_in, sf::Angle angle_in) +sf::Vector2f velocityInDirection(const float speed_in, const sf::Angle angle_in) { return sf::Vector2f{speed_in * std::cos(angle_in.asRadians()), speed_in * std::sin(angle_in.asRadians())}; } diff --git a/src/main.cpp b/src/main.cpp index b015c18..f5b54e5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,23 @@ int main(int argc, char* argv[]) { + bool useImgui{true}; Game game; - game.run(); + + for (int i = 0; i < argc; i++) + { + if (!strcmp(argv[i], "--noImgui")) + { + useImgui = false; + } + } + + if (useImgui) + { + game.run(); + } + else + { + game.runNoImgui(); + } } \ No newline at end of file