From 683096351ff64b301eb025be857d153e3da37f26 Mon Sep 17 00:00:00 2001 From: Floriansylvain Date: Sun, 28 Dec 2025 02:50:59 +0100 Subject: [PATCH] refac: clean base --- CMakeLists.txt | 7 ++- src/DebugUI.cpp | 21 +++++++ src/DebugUI.hpp | 20 +++++++ src/Game.cpp | 69 ++++++++++++++++++++++ src/Game.hpp | 35 +++++++++++ src/GridLines.cpp | 19 ++++++ src/GridLines.hpp | 17 ++++++ src/Player.cpp | 18 ++++++ src/Player.hpp | 20 +++++++ src/main.cpp | 146 +--------------------------------------------- 10 files changed, 228 insertions(+), 144 deletions(-) create mode 100644 src/DebugUI.cpp create mode 100644 src/DebugUI.hpp create mode 100644 src/Game.cpp create mode 100644 src/Game.hpp create mode 100644 src/GridLines.cpp create mode 100644 src/GridLines.hpp create mode 100644 src/Player.cpp create mode 100644 src/Player.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 422a42c..b00f5ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(ASSETS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/assets") set(ASSETS_DEST_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets") +file(GLOB_RECURSE SOURCES "src/*.cpp") + include(FetchContent) FetchContent_Declare(SFML GIT_REPOSITORY https://github.com/SFML/SFML.git @@ -14,7 +16,10 @@ FetchContent_Declare(SFML SYSTEM) FetchContent_MakeAvailable(SFML) -add_executable(main src/main.cpp) +add_executable(main ${SOURCES}) + +target_include_directories(main PRIVATE include) + target_compile_features(main PRIVATE cxx_std_17) target_link_libraries(main PRIVATE SFML::Graphics) diff --git a/src/DebugUI.cpp b/src/DebugUI.cpp new file mode 100644 index 0000000..cd89059 --- /dev/null +++ b/src/DebugUI.cpp @@ -0,0 +1,21 @@ +#include "DebugUI.hpp" +#include "Game.hpp" +#include + +DebugUI::DebugUI() {} + +void DebugUI::update(double dt) { + lastTextUpdateElapsedMs += dt; + + if (lastTextUpdateElapsedMs < 250) + return; + + std::string info = "V-SYNC: " + std::string(VSYNC ? "On" : "Off") + + "\nFrametime: " + std::to_string(dt) + " ms" + + "\nFPS: " + std::to_string(static_cast(1000.0 / dt)); + + text.setString(info); + lastTextUpdateElapsedMs = 0; +} + +void DebugUI::render(sf::RenderWindow &window) { window.draw(text); } diff --git a/src/DebugUI.hpp b/src/DebugUI.hpp new file mode 100644 index 0000000..59607ab --- /dev/null +++ b/src/DebugUI.hpp @@ -0,0 +1,20 @@ +#ifndef DEBUGUI_HPP +#define DEBUGUI_HPP + +#include +#include +#include +#include + +struct DebugUI { + sf::Font font; + sf::Text text{font}; + double lastTextUpdateElapsedMs = 0; + + DebugUI(); + + void update(double dt); + void render(sf::RenderWindow &window); +}; + +#endif // DEBUGUI_HPP diff --git a/src/Game.cpp b/src/Game.cpp new file mode 100644 index 0000000..fbe9089 --- /dev/null +++ b/src/Game.cpp @@ -0,0 +1,69 @@ +#include "Game.hpp" + +Game::Game() : gridLines(WIDTH, HEIGHT, 20.f), player(15.f, sf::Color::Green) { + window.create(sf::VideoMode({WIDTH, HEIGHT}), "SFML Game"); + window.setVerticalSyncEnabled(VSYNC); + + if (!debug.font.openFromFile("assets/Consolas.ttf")) { + window.close(); + } + + worldView.setSize({(float)WIDTH, (float)HEIGHT}); + worldView.setCenter({(float)WIDTH / 2.f, (float)HEIGHT / 2.f}); +} + +void Game::run() { + sf::Clock clock; + while (window.isOpen()) { + double dt = clock.restart().asMicroseconds() / 1000.0; + processEvents(); + update(dt); + render(); + } +} + +void Game::onResize() { + auto windowSize = window.getSize(); + float windowRatio = + static_cast(windowSize.x) / static_cast(windowSize.y); + float viewWidth = 1.0f; + float viewHeight = 1.0f; + float posX = 0.0f; + float posY = 0.0f; + + if (windowRatio > ASPECT) { + viewWidth = ASPECT / windowRatio; + posX = (1.0f - viewWidth) / 2.0f; + } else { + viewHeight = windowRatio / ASPECT; + posY = (1.0f - viewHeight) / 2.0f; + } + + worldView.setViewport(sf::FloatRect({posX, posY}, {viewWidth, viewHeight})); +} + +void Game::processEvents() { + while (const std::optional event = window.pollEvent()) { + if (event->is()) { + window.close(); + } else if (event->is()) { + onResize(); + } + }; +}; + +void Game::update(double dt) { + debug.update(dt); + player.update(dt, window, worldView); +}; + +void Game::render() { + window.clear(); + window.setView(worldView); + + gridLines.render(window); + debug.render(window); + player.render(window); + + window.display(); +}; diff --git a/src/Game.hpp b/src/Game.hpp new file mode 100644 index 0000000..9c47155 --- /dev/null +++ b/src/Game.hpp @@ -0,0 +1,35 @@ +#ifndef GAME_HPP +#define GAME_HPP + +#include + +#include "DebugUI.hpp" +#include "GridLines.hpp" +#include "Player.hpp" + +constexpr bool VSYNC = true; +constexpr int WIDTH = 1920; +constexpr int HEIGHT = 1080; +constexpr int DEBUG_REFRESH_RATE_IN_MS = 250; +constexpr float ASPECT = 16.f / 9.f; + +class Game { +public: + Game(); + void run(); + +private: + sf::RenderWindow window; + sf::View worldView; + + Player player; + DebugUI debug; + GridLines gridLines; + + void onResize(); + void processEvents(); + void update(double dt); + void render(); +}; + +#endif // GAME_HPP diff --git a/src/GridLines.cpp b/src/GridLines.cpp new file mode 100644 index 0000000..67d00b0 --- /dev/null +++ b/src/GridLines.cpp @@ -0,0 +1,19 @@ +#include "GridLines.hpp" +#include + +GridLines::GridLines(float width, float height, float spacing) + : m_lines(sf::PrimitiveType::Lines) { + sf::Color gray(64, 64, 64); + + for (float x = 0; x <= width; x += spacing) { + m_lines.append({{x, 0.f}, gray}); + m_lines.append({{x, height}, gray}); + } + + for (float y = 0; y <= height; y += spacing) { + m_lines.append({{0.f, y}, gray}); + m_lines.append({{width, y}, gray}); + } +} + +void GridLines::render(sf::RenderWindow &window) const { window.draw(m_lines); } diff --git a/src/GridLines.hpp b/src/GridLines.hpp new file mode 100644 index 0000000..255f3d5 --- /dev/null +++ b/src/GridLines.hpp @@ -0,0 +1,17 @@ +#ifndef GRIDLINES_HPP +#define GRIDLINES_HPP + +#include +#include + +class GridLines { +public: + GridLines(float width, float height, float spacing = 20.f); + + void render(sf::RenderWindow &window) const; + +private: + sf::VertexArray m_lines; +}; + +#endif // GRIDLINES_HPP diff --git a/src/Player.cpp b/src/Player.cpp new file mode 100644 index 0000000..8c63c66 --- /dev/null +++ b/src/Player.cpp @@ -0,0 +1,18 @@ +#include "Player.hpp" +#include +#include + +Player::Player(float size, sf::Color color) : circleShape(size) { + circleShape.setFillColor(color); +} + +void Player::update(double dt, sf::RenderWindow &window, const sf::View &view) { + auto shapeRadius = circleShape.getRadius(); + auto mousePos = sf::Mouse::getPosition(window); + auto mousePosWorld = window.mapPixelToCoords(mousePos, view); + + circleShape.setPosition( + {mousePosWorld.x - shapeRadius, mousePosWorld.y - shapeRadius}); +}; + +void Player::render(sf::RenderWindow &window) { window.draw(circleShape); }; diff --git a/src/Player.hpp b/src/Player.hpp new file mode 100644 index 0000000..e63ee19 --- /dev/null +++ b/src/Player.hpp @@ -0,0 +1,20 @@ +#ifndef PLAYER_HPP +#define PLAYER_HPP + +#include +#include +#include +#include + +class Player { +public: + Player(float size, sf::Color color); + + void update(double dt, sf::RenderWindow &window, const sf::View &view); + void render(sf::RenderWindow &window); + +private: + sf::CircleShape circleShape; +}; + +#endif // PLAYER_HPP diff --git a/src/main.cpp b/src/main.cpp index 0d5b788..47bee78 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,148 +1,8 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -constexpr int DEBUG_REFRESH_RATE_IN_MS = 250; -constexpr bool VSYNC = true; -constexpr int WIDTH = 1920; -constexpr int HEIGHT = 1080; -constexpr float ASPECT = 16.f / 9.f; - -constexpr float SPEED = 3.f; - -void updateShapePosition(sf::CircleShape &shape, sf::RenderWindow &window, - sf::View &worldView) { - if (!window.hasFocus()) - return; - - auto shapeRadius = shape.getRadius(); - auto mousePos = sf::Mouse::getPosition(window); - auto mousePosWorld = window.mapPixelToCoords(mousePos, worldView); - - shape.setPosition(sf::Vector2f(mousePosWorld.x - shapeRadius, - mousePosWorld.y - shapeRadius)); -} - -std::string getDebugText(double elapsedMilliseconds, sf::View &worldView) { - if (elapsedMilliseconds <= 0) - return ""; - - auto viewPos = worldView.getCenter(); - - return "V-SYNC: " + std::string(VSYNC ? "On" : "Off") + - "\nFrametime: " + std::to_string(elapsedMilliseconds) + - "\nFPS: " + std::to_string((int)(1000 / elapsedMilliseconds)) + - "\n\nView x, y: " + std::to_string((int)viewPos.x) + ", " + - std::to_string((int)viewPos.y); -} - -void drawGrid(sf::RenderWindow &window) { - sf::Color gray(64, 64, 64); - sf::VertexArray lines(sf::PrimitiveType::Lines); - - for (float x = 0; x <= WIDTH; x += 20.f) { - lines.append(sf::Vertex{{x, 0.f}, gray}); - lines.append(sf::Vertex{{x, HEIGHT}, gray}); - } - - for (float y = 0; y <= HEIGHT; y += 20.f) { - lines.append(sf::Vertex{{0.f, y}, gray}); - lines.append(sf::Vertex{{WIDTH, y}, gray}); - } - - window.draw(lines); -} +#include "Game.hpp" int main() { - sf::RenderWindow window(sf::VideoMode({WIDTH, HEIGHT}), "Whatever SFML"); - window.setVerticalSyncEnabled(VSYNC); - - sf::RectangleShape worldLimit({WIDTH - 6, HEIGHT - 6}); - worldLimit.setFillColor(sf::Color::Transparent); - worldLimit.setOutlineColor(sf::Color::Red); - worldLimit.setOutlineThickness(3.f); - worldLimit.setPosition({3.f, 3.f}); - - sf::CircleShape shape(15.f); - shape.setFillColor(sf::Color(100, 250, 50)); - shape.setPosition({0, HEIGHT}); - - sf::Clock clock; - - sf::Font font; - if (!font.openFromFile("assets/Consolas.ttf")) - return 0; - - sf::Text debugUI(font); - debugUI.setString(""); - - sf::View worldView; - worldView.setSize({WIDTH, HEIGHT}); - worldView.setCenter({(float)WIDTH / 2, (float)HEIGHT / 2}); - - double lastTextUpdateElapsedMs = 0; - - while (window.isOpen()) { - while (const std::optional event = window.pollEvent()) { - if (event->is()) { - window.close(); - return 0; - } else if (event->is()) { - auto windowSize = window.getSize(); - float windowRatio = - static_cast(windowSize.x) / static_cast(windowSize.y); - float viewWidth = 1.0f; - float viewHeight = 1.0f; - float posX = 0.0f; - float posY = 0.0f; - - if (windowRatio > ASPECT) { - viewWidth = ASPECT / windowRatio; - posX = (1.0f - viewWidth) / 2.0f; - } else { - viewHeight = windowRatio / ASPECT; - posY = (1.0f - viewHeight) / 2.0f; - } - - worldView.setViewport( - sf::FloatRect({posX, posY}, {viewWidth, viewHeight})); - } - } - - updateShapePosition(shape, window, worldView); - - window.clear(); - - window.setView(worldView); - window.draw(shape); - drawGrid(window); - // window.draw(worldLimit); - window.draw(debugUI); - - window.display(); - - double elapsedMilliseconds = - (double)clock.restart().asMicroseconds() / 1000; - - lastTextUpdateElapsedMs += elapsedMilliseconds; - - if (lastTextUpdateElapsedMs > DEBUG_REFRESH_RATE_IN_MS) { - debugUI.setString(getDebugText(elapsedMilliseconds, worldView)); - lastTextUpdateElapsedMs = 0; - } - } + Game game = Game(); + game.run(); return 0; }