From 885ed1ec4b5c450be916f37f915db5787bbe9cda Mon Sep 17 00:00:00 2001 From: Florian Sylvain Date: Sun, 11 May 2025 01:01:18 +0200 Subject: [PATCH] refac: moved draw & input code out of game class --- CMakeLists.txt | 2 +- README.md | 104 +++---------------------------------------- old_README.md | 101 +++++++++++++++++++++++++++++++++++++++++ src/DebugDraw.cpp | 41 +++++++++++++++++ src/DebugDraw.hpp | 14 ++++++ src/Game.cpp | 70 +++++++---------------------- src/Game.hpp | 9 +--- src/InputManager.cpp | 18 ++++++++ src/InputManager.hpp | 19 ++++++++ 9 files changed, 217 insertions(+), 161 deletions(-) create mode 100644 old_README.md create mode 100644 src/DebugDraw.cpp create mode 100644 src/DebugDraw.hpp create mode 100644 src/InputManager.cpp create mode 100644 src/InputManager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fd4fe72..ec4448a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,4 +17,4 @@ file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS src/*.hpp) add_executable(SFMLplayground ${SOURCES} ${HEADERS}) target_compile_features(SFMLplayground PRIVATE cxx_std_17) -target_link_libraries(SFMLplayground PRIVATE SFML::Graphics) \ No newline at end of file +target_link_libraries(SFMLplayground PRIVATE SFML::Graphics) diff --git a/README.md b/README.md index 84576c0..1028983 100644 --- a/README.md +++ b/README.md @@ -1,101 +1,9 @@ -# CMake SFML Project Template +# SFML Playground -This repository template should allow for a fast and hassle-free kick start of your next SFML project using CMake. -Thanks to [GitHub's nature of templates](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template), you can fork this repository without inheriting its Git history. +Simple CMake project w/ SFML 3 to play around with. -The template starts out very basic, but might receive additional features over time: +## TODO -- Basic CMake script to build your project and link SFML on any operating system -- Basic [GitHub Actions](https://github.com/features/actions) script for all major platforms - -## How to Use - -1. Install [Git](https://git-scm.com/downloads) and [CMake](https://cmake.org/download/). Use your system's package manager if available. -2. Follow [GitHub's instructions](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) for how to use their project template feature to create your own project. If you don't want to use GitHub, see the section below. -3. Clone your new GitHub repo and open the repo in your text editor of choice. -4. Open [CMakeLists.txt](CMakeLists.txt). Rename the project and the target name of the executable to whatever name you want. Make sure to change all occurrences. -5. If you want to add or remove any .cpp files, change the source files listed in the `add_executable` call in CMakeLists.txt to match the source files your project requires. If you plan on keeping the default main.cpp file then no changes are required. -6. If your code uses the Audio or Network modules then add `SFML::Audio` or `SFML::Network` to the `target_link_libraries` call alongside the existing `SFML::Graphics` library that is being linked. -7. If you use Linux, install SFML's dependencies using your system package manager. On Ubuntu and other Debian-based distributions you can use the following commands: - ``` - sudo apt update - sudo apt install \ - libxrandr-dev \ - libxcursor-dev \ - libxi-dev \ - libudev-dev \ - libfreetype-dev \ - libflac-dev \ - libvorbis-dev \ - libgl1-mesa-dev \ - libegl1-mesa-dev \ - libfreetype-dev - ``` -8. Configure and build your project. Most popular IDEs support CMake projects with very little effort on your part. - - - [VS Code](https://code.visualstudio.com) via the [CMake extension](https://code.visualstudio.com/docs/cpp/cmake-linux) - - [Visual Studio](https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=msvc-170) - - [CLion](https://www.jetbrains.com/clion/features/cmake-support.html) - - [Qt Creator](https://doc.qt.io/qtcreator/creator-project-cmake.html) - - Using CMake from the command line is straightforward as well. - Be sure to run these commands in the root directory of the project you just created. - - ``` - cmake -B build - cmake --build build - ``` - -9. Enjoy! - -## Upgrading SFML - -SFML is found via CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) module. -FetchContent automatically downloads SFML from GitHub and builds it alongside your own code. -Beyond the convenience of not having to install SFML yourself, this ensures ABI compatibility and simplifies things like specifying static versus shared libraries. - -Modifying what version of SFML you want is as easy as changing the `GIT_TAG` argument. -Currently it uses SFML 3 via the `3.0.0` tag. - -## But I want to... - -Modify CMake options by adding them as configuration parameters (with a `-D` flag) or by modifying the contents of CMakeCache.txt and rebuilding. - -### Not use GitHub - -You can use this project without a GitHub account by [downloading the contents](https://github.com/SFML/cmake-sfml-project/archive/refs/heads/master.zip) of the repository as a ZIP archive and unpacking it locally. -This approach also avoids using Git entirely if you would prefer to not do that. - -### Change Compilers - -See the variety of [`CMAKE__COMPILER`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER.html) options. -In particular you'll want to modify `CMAKE_CXX_COMPILER` to point to the C++ compiler you wish to use. - -### Change Compiler Optimizations - -CMake abstracts away specific optimizer flags through the [`CMAKE_BUILD_TYPE`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) option. -By default this project recommends `Release` builds which enable optimizations. -Other build types include `Debug` builds which enable debug symbols but disable optimizations. -If you're using a multi-configuration generator (as is often the case on Windows), you can modify the [`CMAKE_CONFIGURATION_TYPES`](https://cmake.org/cmake/help/latest/variable/CMAKE_CONFIGURATION_TYPES.html#variable:CMAKE_CONFIGURATION_TYPES) option. - -### Change Generators - -While CMake will attempt to pick a suitable default generator, some systems offer a number of generators to choose from. -Ubuntu, for example, offers Makefiles and Ninja as two potential options. -For a list of generators, click [here](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). -To modify the generator you're using you must reconfigure your project providing a `-G` flag with a value corresponding to the generator you want. -You can't simply modify an entry in the CMakeCache.txt file unlike the above options. -Then you may rebuild your project with this new generator. - -## More Reading - -Here are some useful resources if you want to learn more about CMake: - -- [Official CMake Tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/) -- [How to Use CMake Without the Agonizing Pain - Part 1](https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-1.html) -- [How to Use CMake Without the Agonizing Pain - Part 2](https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-2.html) -- [Better CMake YouTube series by Jefferon Amstutz](https://www.youtube.com/playlist?list=PL8i3OhJb4FNV10aIZ8oF0AA46HgA2ed8g) - -## License - -The source code is dual licensed under Public Domain and MIT -- choose whichever you prefer. +- [ ] Add a toggle for debug stuff +- [ ] Add debug text (for ball velocity, position, rest status, etc.) +- [ ] Refactor game class to split input handling and debug stuff into their own classes diff --git a/old_README.md b/old_README.md new file mode 100644 index 0000000..84576c0 --- /dev/null +++ b/old_README.md @@ -0,0 +1,101 @@ +# CMake SFML Project Template + +This repository template should allow for a fast and hassle-free kick start of your next SFML project using CMake. +Thanks to [GitHub's nature of templates](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template), you can fork this repository without inheriting its Git history. + +The template starts out very basic, but might receive additional features over time: + +- Basic CMake script to build your project and link SFML on any operating system +- Basic [GitHub Actions](https://github.com/features/actions) script for all major platforms + +## How to Use + +1. Install [Git](https://git-scm.com/downloads) and [CMake](https://cmake.org/download/). Use your system's package manager if available. +2. Follow [GitHub's instructions](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template) for how to use their project template feature to create your own project. If you don't want to use GitHub, see the section below. +3. Clone your new GitHub repo and open the repo in your text editor of choice. +4. Open [CMakeLists.txt](CMakeLists.txt). Rename the project and the target name of the executable to whatever name you want. Make sure to change all occurrences. +5. If you want to add or remove any .cpp files, change the source files listed in the `add_executable` call in CMakeLists.txt to match the source files your project requires. If you plan on keeping the default main.cpp file then no changes are required. +6. If your code uses the Audio or Network modules then add `SFML::Audio` or `SFML::Network` to the `target_link_libraries` call alongside the existing `SFML::Graphics` library that is being linked. +7. If you use Linux, install SFML's dependencies using your system package manager. On Ubuntu and other Debian-based distributions you can use the following commands: + ``` + sudo apt update + sudo apt install \ + libxrandr-dev \ + libxcursor-dev \ + libxi-dev \ + libudev-dev \ + libfreetype-dev \ + libflac-dev \ + libvorbis-dev \ + libgl1-mesa-dev \ + libegl1-mesa-dev \ + libfreetype-dev + ``` +8. Configure and build your project. Most popular IDEs support CMake projects with very little effort on your part. + + - [VS Code](https://code.visualstudio.com) via the [CMake extension](https://code.visualstudio.com/docs/cpp/cmake-linux) + - [Visual Studio](https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=msvc-170) + - [CLion](https://www.jetbrains.com/clion/features/cmake-support.html) + - [Qt Creator](https://doc.qt.io/qtcreator/creator-project-cmake.html) + + Using CMake from the command line is straightforward as well. + Be sure to run these commands in the root directory of the project you just created. + + ``` + cmake -B build + cmake --build build + ``` + +9. Enjoy! + +## Upgrading SFML + +SFML is found via CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) module. +FetchContent automatically downloads SFML from GitHub and builds it alongside your own code. +Beyond the convenience of not having to install SFML yourself, this ensures ABI compatibility and simplifies things like specifying static versus shared libraries. + +Modifying what version of SFML you want is as easy as changing the `GIT_TAG` argument. +Currently it uses SFML 3 via the `3.0.0` tag. + +## But I want to... + +Modify CMake options by adding them as configuration parameters (with a `-D` flag) or by modifying the contents of CMakeCache.txt and rebuilding. + +### Not use GitHub + +You can use this project without a GitHub account by [downloading the contents](https://github.com/SFML/cmake-sfml-project/archive/refs/heads/master.zip) of the repository as a ZIP archive and unpacking it locally. +This approach also avoids using Git entirely if you would prefer to not do that. + +### Change Compilers + +See the variety of [`CMAKE__COMPILER`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER.html) options. +In particular you'll want to modify `CMAKE_CXX_COMPILER` to point to the C++ compiler you wish to use. + +### Change Compiler Optimizations + +CMake abstracts away specific optimizer flags through the [`CMAKE_BUILD_TYPE`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) option. +By default this project recommends `Release` builds which enable optimizations. +Other build types include `Debug` builds which enable debug symbols but disable optimizations. +If you're using a multi-configuration generator (as is often the case on Windows), you can modify the [`CMAKE_CONFIGURATION_TYPES`](https://cmake.org/cmake/help/latest/variable/CMAKE_CONFIGURATION_TYPES.html#variable:CMAKE_CONFIGURATION_TYPES) option. + +### Change Generators + +While CMake will attempt to pick a suitable default generator, some systems offer a number of generators to choose from. +Ubuntu, for example, offers Makefiles and Ninja as two potential options. +For a list of generators, click [here](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html). +To modify the generator you're using you must reconfigure your project providing a `-G` flag with a value corresponding to the generator you want. +You can't simply modify an entry in the CMakeCache.txt file unlike the above options. +Then you may rebuild your project with this new generator. + +## More Reading + +Here are some useful resources if you want to learn more about CMake: + +- [Official CMake Tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/) +- [How to Use CMake Without the Agonizing Pain - Part 1](https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-1.html) +- [How to Use CMake Without the Agonizing Pain - Part 2](https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-2.html) +- [Better CMake YouTube series by Jefferon Amstutz](https://www.youtube.com/playlist?list=PL8i3OhJb4FNV10aIZ8oF0AA46HgA2ed8g) + +## License + +The source code is dual licensed under Public Domain and MIT -- choose whichever you prefer. diff --git a/src/DebugDraw.cpp b/src/DebugDraw.cpp new file mode 100644 index 0000000..4366af7 --- /dev/null +++ b/src/DebugDraw.cpp @@ -0,0 +1,41 @@ +#include "DebugDraw.hpp" + +#include +#include +#include + +#include "VectorMath.hpp" + +float clamp(float value, float minVal, float maxVal) { + return std::max(minVal, std::min(value, maxVal)); +} + +void DebugDraw::drawLine(sf::RenderWindow& window, const sf::Vector2f& start, + const sf::Vector2f& direction, float length, + const sf::Color& color) { + sf::Vector2f endPoint = start + VectorMath::normalize(direction) * length; + sf::Vertex line[] = {{start, color}, {endPoint, color}}; + + window.draw(line, 2, sf::PrimitiveType::Lines); +} + +void DebugDraw::drawDirectionLine(sf::RenderWindow& window, const Ball* ball) { + sf::Vector2f ballCenter = ball->getPosition(); + sf::Vector2i mousePixel = sf::Mouse::getPosition(window); + sf::Vector2f mouseWorld(static_cast(mousePixel.x), + static_cast(mousePixel.y)); + sf::Vector2f dir = mouseWorld - ballCenter; + + drawLine(window, ballCenter, dir, 100.f, sf::Color::Green); +} + +void DebugDraw::drawVelocityLine(sf::RenderWindow& window, const Ball* ball) { + if (ball->isAtRest()) return; + + sf::Vector2f ballCenter = ball->getPosition(); + sf::Vector2f velocity = ball->getVelocity(); + float velLength = VectorMath::length(velocity); + float clampedLength = std::max(0.f, std::min(velLength, 100.f)); + + drawLine(window, ballCenter, velocity, clampedLength, sf::Color::Blue); +} diff --git a/src/DebugDraw.hpp b/src/DebugDraw.hpp new file mode 100644 index 0000000..a24f098 --- /dev/null +++ b/src/DebugDraw.hpp @@ -0,0 +1,14 @@ +#pragma once +#include +#include + +#include "Ball.hpp" + +class DebugDraw { + public: + static void drawLine(sf::RenderWindow& window, const sf::Vector2f& start, + const sf::Vector2f& direction, float length, + const sf::Color& color); + static void drawDirectionLine(sf::RenderWindow& window, const Ball* ball); + static void drawVelocityLine(sf::RenderWindow& window, const Ball* ball); +}; diff --git a/src/Game.cpp b/src/Game.cpp index d524d5f..a5f7720 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -4,9 +4,13 @@ #include #include "Constants.hpp" +#include "DebugDraw.hpp" #include "VectorMath.hpp" -Game::Game() { +Game::Game() + : m_inputManager( + std::bind(&Game::processKeyPressed, this, std::placeholders::_1), + std::bind(&Game::processMousePressed, this, std::placeholders::_1)) { m_window.create(sf::VideoMode({Constants::WIDTH, Constants::HEIGHT}), "SFML Playground"); m_window.setVerticalSyncEnabled(true); @@ -18,7 +22,7 @@ Game::Game() { sf::Vector2f(400.f, 0.f))); } -void Game::processKeyPressed(const sf::Event::KeyPressed& kP) { +void Game::processKeyPressed(const sf::Event::KeyPressed &kP) { if (kP.code == sf::Keyboard::Key::Equal) { m_timeScale *= 1.1f; } else if (kP.code == sf::Keyboard::Key::Hyphen) { @@ -27,26 +31,13 @@ void Game::processKeyPressed(const sf::Event::KeyPressed& kP) { } } -void Game::processMousePressed(const sf::Event::MouseButtonPressed& mP) { +void Game::processMousePressed(const sf::Event::MouseButtonPressed &mP) { if (mP.button != sf::Mouse::Button::Left) return; handleMouseClick(sf::Vector2i(mP.position.x, mP.position.y)); } -void Game::processEvents() { - while (const std::optional event = m_window.pollEvent()) { - if (event->is()) { - m_window.close(); - return; - } - if (auto kP = event->getIf()) - processKeyPressed(*kP); - if (auto mP = event->getIf()) - processMousePressed(*mP); - } -} - -void Game::handleMouseClick(const sf::Vector2i& mousePos) { - auto* ball = dynamic_cast(m_objects[0].get()); +void Game::handleMouseClick(const sf::Vector2i &mousePos) { + auto *ball = dynamic_cast(m_objects[0].get()); if (!ball) return; sf::Vector2f mouseWorld(static_cast(mousePos.x), @@ -58,48 +49,17 @@ void Game::handleMouseClick(const sf::Vector2i& mousePos) { void Game::update() { float dt = m_clock.restart().asSeconds() * m_timeScale; - for (auto& object : m_objects) object->update(dt); -} - -void Game::drawLine(const sf::Vector2f& start, const sf::Vector2f& direction, - float length, const sf::Color& color) { - float dirLength = - std::sqrt(direction.x * direction.x + direction.y * direction.y); - sf::Vector2f dirNorm = - (dirLength != 0.f) ? direction / dirLength : sf::Vector2f(1.f, 0.f); - sf::Vector2f endPoint = start + dirNorm * length; - - sf::Vertex line[] = {{start, color}, {endPoint, color}}; - m_window.draw(line, 2, sf::PrimitiveType::Lines); -} - -void Game::drawDirectionLine(const Ball* ball) { - sf::Vector2f ballCenter = ball->getPosition(); - sf::Vector2i mousePixel = sf::Mouse::getPosition(m_window); - sf::Vector2f mouseWorld(static_cast(mousePixel.x), - static_cast(mousePixel.y)); - sf::Vector2f dir = mouseWorld - ballCenter; - drawLine(ballCenter, dir, 100.f, sf::Color::Green); -} - -void Game::drawVelocityLine(const Ball* ball) { - if (ball->isAtRest()) return; - sf::Vector2f ballCenter = ball->getPosition(); - sf::Vector2f velocity = ball->getVelocity(); - float velLength = - std::sqrt(velocity.x * velocity.x + velocity.y * velocity.y); - float clampedLength = std::min(100.f, std::max(0.f, velLength)); - drawLine(ballCenter, velocity, clampedLength, sf::Color::Blue); + for (auto &object : m_objects) object->update(dt); } void Game::render() { m_window.clear(sf::Color::Black); - for (auto& object : m_objects) object->draw(m_window); + for (auto &object : m_objects) object->draw(m_window); - auto* ball = dynamic_cast(m_objects[0].get()); + auto *ball = dynamic_cast(m_objects[0].get()); if (ball) { - drawDirectionLine(ball); - drawVelocityLine(ball); + DebugDraw::drawDirectionLine(m_window, ball); + DebugDraw::drawVelocityLine(m_window, ball); } m_window.display(); @@ -107,7 +67,7 @@ void Game::render() { void Game::run() { while (m_window.isOpen()) { - processEvents(); + m_inputManager.processEvents(m_window); update(); render(); } diff --git a/src/Game.hpp b/src/Game.hpp index 0dc93a3..68d9c4e 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -7,6 +7,7 @@ #include #include "Ball.hpp" +#include "InputManager.hpp" #include "PhysicalObject.hpp" class Ball; @@ -18,19 +19,13 @@ class Game { sf::RenderWindow m_window; std::vector> m_objects; sf::Clock m_clock; - - void processEvents(); + InputManager m_inputManager; void processKeyPressed(const sf::Event::KeyPressed& keyPressed); void processMousePressed(const sf::Event::MouseButtonPressed& mousePressed); void handleMouseClick(const sf::Vector2i& mousePos); void update(); void render(); - void drawLine(const sf::Vector2f& start, const sf::Vector2f& direction, - float length, const sf::Color& color); - void drawDirectionLine(const Ball* ball); - void drawVelocityLine(const Ball* ball); - public: Game(); void run(); diff --git a/src/InputManager.cpp b/src/InputManager.cpp new file mode 100644 index 0000000..d717db1 --- /dev/null +++ b/src/InputManager.cpp @@ -0,0 +1,18 @@ +#include "InputManager.hpp" + +#include + +InputManager::InputManager(KeyCallback keyCb, MouseCallback mouseCb) + : m_keyCallback(std::move(keyCb)), m_mouseCallback(std::move(mouseCb)) {} + +void InputManager::processEvents(sf::Window& window) { + while (const std::optional event = window.pollEvent()) { + if (event->is()) { + window.close(); + return; + } + if (auto kP = event->getIf()) m_keyCallback(*kP); + if (auto mP = event->getIf()) + m_mouseCallback(*mP); + } +} diff --git a/src/InputManager.hpp b/src/InputManager.hpp new file mode 100644 index 0000000..405e51b --- /dev/null +++ b/src/InputManager.hpp @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include + +class InputManager { + public: + using KeyCallback = std::function; + using MouseCallback = + std::function; + + InputManager(KeyCallback keyCb, MouseCallback mouseCb); + + void processEvents(sf::Window& window); + + private: + KeyCallback m_keyCallback; + MouseCallback m_mouseCallback; +};