From 60c33a796551d6cbd7d66081b9d273953313840f Mon Sep 17 00:00:00 2001 From: Florian Sylvain Date: Wed, 14 May 2025 00:26:21 +0200 Subject: [PATCH] refac: rendering, debug overlay, & game mechanics --- .github/workflows/ci.yml | 39 ----------------------------------- src/Ball.cpp | 18 ++++++++-------- src/BatchRenderer.cpp | 40 +++++++++++++++--------------------- src/Constants.hpp | 6 +++--- src/DebugDraw.cpp | 2 +- src/DebugOverlay.cpp | 44 +++++++++++++++++++++++++++++++++------- src/DebugOverlay.hpp | 7 +++++++ src/Game.cpp | 6 ++++-- 8 files changed, 77 insertions(+), 85 deletions(-) delete mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 2e35fb5..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: CI - -on: [push, pull_request] - -defaults: - run: - shell: bash - -jobs: - build: - name: ${{ matrix.platform.name }} ${{ matrix.config.name }} - runs-on: ${{ matrix.platform.os }} - - strategy: - fail-fast: false - matrix: - platform: - - { name: Windows VS2019, os: windows-2019 } - - { name: Windows VS2022, os: windows-2022 } - - { name: Linux GCC, os: ubuntu-latest } - - { name: Linux Clang, os: ubuntu-latest, flags: -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ } - - { name: macOS, os: macos-latest } - config: - - { name: Shared, flags: -DBUILD_SHARED_LIBS=TRUE } - - { name: Static, flags: -DBUILD_SHARED_LIBS=FALSE } - - steps: - - name: Install Linux Dependencies - if: runner.os == 'Linux' - run: sudo apt-get update && sudo apt-get install libxrandr-dev libxcursor-dev libxi-dev libudev-dev libflac-dev libvorbis-dev libgl1-mesa-dev libegl1-mesa-dev libfreetype-dev - - - name: Checkout - uses: actions/checkout@v4 - - - name: Configure - run: cmake -B build ${{matrix.platform.flags}} ${{matrix.config.flags}} - - - name: Build - run: cmake --build build --config Release diff --git a/src/Ball.cpp b/src/Ball.cpp index 897cc67..33a43df 100644 --- a/src/Ball.cpp +++ b/src/Ball.cpp @@ -69,15 +69,15 @@ void Ball::updateColor() { constexpr float TRANSITION_SPEED = 0.05f; sf::Color newColor; - newColor.r = static_cast(static_cast(currentColor.r) + - TRANSITION_SPEED * - (targetColor.r - currentColor.r)); - newColor.g = static_cast(static_cast(currentColor.g) + - TRANSITION_SPEED * - (targetColor.g - currentColor.g)); - newColor.b = static_cast(static_cast(currentColor.b) + - TRANSITION_SPEED * - (targetColor.b - currentColor.b)); + newColor.r = static_cast( + static_cast(currentColor.r) + + TRANSITION_SPEED * static_cast(targetColor.r - currentColor.r)); + newColor.g = static_cast( + static_cast(currentColor.g) + + TRANSITION_SPEED * static_cast(targetColor.g - currentColor.g)); + newColor.b = static_cast( + static_cast(currentColor.b) + + TRANSITION_SPEED * static_cast(targetColor.b - currentColor.b)); newColor.a = 255; m_shape.setFillColor(newColor); diff --git a/src/BatchRenderer.cpp b/src/BatchRenderer.cpp index 59265fd..f68ef4b 100644 --- a/src/BatchRenderer.cpp +++ b/src/BatchRenderer.cpp @@ -43,36 +43,28 @@ void BatchRenderer::addBall(const Ball &ball) { const float radius = ball.getRadius(); const sf::Color color = ball.getColor(); - sf::Vertex topLeft; - sf::Vertex topRight; - sf::Vertex bottomRight; - sf::Vertex bottomLeft; - - topLeft.position = sf::Vector2f(position.x - radius, position.y - radius); - topRight.position = sf::Vector2f(position.x + radius, position.y - radius); - bottomRight.position = sf::Vector2f(position.x + radius, position.y + radius); - bottomLeft.position = sf::Vector2f(position.x - radius, position.y + radius); + sf::Vertex vertices[4]; + vertices[0].position = sf::Vector2f(position.x - radius, position.y - radius); + vertices[1].position = sf::Vector2f(position.x + radius, position.y - radius); + vertices[2].position = sf::Vector2f(position.x + radius, position.y + radius); + vertices[3].position = sf::Vector2f(position.x - radius, position.y + radius); const float xSize = static_cast(m_circleTexture.getSize().x); const float ySize = static_cast(m_circleTexture.getSize().y); + vertices[0].texCoords = sf::Vector2f(0, 0); + vertices[1].texCoords = sf::Vector2f(xSize, 0); + vertices[2].texCoords = sf::Vector2f(xSize, ySize); + vertices[3].texCoords = sf::Vector2f(0, ySize); - topLeft.texCoords = sf::Vector2f(0, 0); - topRight.texCoords = sf::Vector2f(xSize, 0); - bottomRight.texCoords = sf::Vector2f(xSize, ySize); - bottomLeft.texCoords = sf::Vector2f(0, ySize); + for (auto &v : vertices) v.color = color; - topLeft.color = color; - topRight.color = color; - bottomRight.color = color; - bottomLeft.color = color; + m_vertices.append(vertices[0]); + m_vertices.append(vertices[1]); + m_vertices.append(vertices[2]); - m_vertices.append(topLeft); - m_vertices.append(topRight); - m_vertices.append(bottomRight); - - m_vertices.append(topLeft); - m_vertices.append(bottomRight); - m_vertices.append(bottomLeft); + m_vertices.append(vertices[0]); + m_vertices.append(vertices[2]); + m_vertices.append(vertices[3]); } void BatchRenderer::draw(sf::RenderWindow &window) const { diff --git a/src/Constants.hpp b/src/Constants.hpp index 50e471f..6a8f8e1 100644 --- a/src/Constants.hpp +++ b/src/Constants.hpp @@ -5,9 +5,9 @@ constexpr int WIDTH = 1920; constexpr int HEIGHT = 1080; constexpr float GRAVITY = 781.f; constexpr float RESTITUTION = 0.8f; -constexpr float FRICTION = 0.9f; +constexpr float FRICTION = 0.99f; constexpr float IMPULSE = 1000.f; constexpr float REST_PIXEL_VELOCITY = 2.0f; -constexpr float BALL_RADIUS = 50.f; -constexpr unsigned BALL_QUANTITY = 10; +constexpr float BALL_RADIUS = 20.f; +constexpr unsigned BALL_QUANTITY = 20; } // namespace Constants diff --git a/src/DebugDraw.cpp b/src/DebugDraw.cpp index 135f5df..5bd9559 100644 --- a/src/DebugDraw.cpp +++ b/src/DebugDraw.cpp @@ -38,7 +38,7 @@ void DebugDraw::addVelocityLine(sf::VertexArray &lines, const Ball *ball) { const float velLength = VectorMath::length(velocity); const float clampedLength = std::max(0.f, std::min(velLength, 100.f)); - addLine(lines, ballCenter, velocity, clampedLength, sf::Color::Red); + addLine(lines, ballCenter, velocity, clampedLength, sf::Color::Blue); } void DebugDraw::drawBatchedLines(sf::RenderWindow &window, diff --git a/src/DebugOverlay.cpp b/src/DebugOverlay.cpp index e577c70..b994129 100644 --- a/src/DebugOverlay.cpp +++ b/src/DebugOverlay.cpp @@ -1,32 +1,62 @@ #include "DebugOverlay.hpp" +#include #include +namespace { + +constexpr float OVERLAY_MARGIN = 5.0f; +constexpr unsigned int FONT_SIZE = 18; +constexpr float AVG_UPDATE_INTERVAL = 0.5f; +constexpr float TEXT_UPDATE_INTERVAL = 0.05f; +} // namespace + DebugOverlay::DebugOverlay(const std::string &fontPath) : m_font(fontPath), m_text(m_font) { - m_text.setCharacterSize(18); + m_text.setCharacterSize(FONT_SIZE); m_text.setFillColor(sf::Color::White); - m_text.setPosition(sf::Vector2f(5.f, 5.f)); + m_text.setPosition({OVERLAY_MARGIN, OVERLAY_MARGIN}); + m_frameTimeHistory.fill(0.0f); } void DebugOverlay::update(const int drawCalls, const float timeScale, const sf::RenderWindow &window, const size_t threadCount, const size_t ballsPerThread) { - const float elapsed = m_fpsClock.restart().asSeconds(); - if (elapsed > 0.2f) m_fps = 1.f / elapsed; + const float frameTime = m_fpsClock.restart().asSeconds(); + + m_frameTimeHistory[m_currentFrameIndex] = frameTime; + m_currentFrameIndex = (m_currentFrameIndex + 1) % FRAME_HISTORY_SIZE; + + m_timeSinceLastAvgUpdate += frameTime; + if (m_timeSinceLastAvgUpdate >= AVG_UPDATE_INTERVAL) { + m_averageFrametime = 0.0f; + for (const float time : m_frameTimeHistory) m_averageFrametime += time; + m_averageFrametime /= FRAME_HISTORY_SIZE; + m_timeSinceLastAvgUpdate = 0.0f; + } + + m_timeSinceLastUpdate += frameTime; + if (m_timeSinceLastUpdate < TEXT_UPDATE_INTERVAL) return; + m_timeSinceLastUpdate = 0.0f; const sf::Vector2i mousePos = sf::Mouse::getPosition(window); std::ostringstream oss; + oss << "Draw calls: " << drawCalls << "\n"; - oss << "Framerate: " << m_fps << " FPS\n"; - oss << "Frame time: " << (elapsed * 1000.f) << " ms\n"; + + oss << std::fixed << std::setprecision(3); + oss << "Frame time: " << (frameTime * 1000.0f) << " ms\n"; + oss << "Frame time (avg): " << (m_averageFrametime * 1000.0f) << " ms\n"; + + oss << std::defaultfloat << std::setprecision(6); oss << "Mouse: " << mousePos.x << ", " << mousePos.y << "\n"; oss << "Time scale: " << timeScale << "\n"; oss << "\nThreads: " << threadCount; oss << "\nBalls per thread: " << ballsPerThread; + m_text.setString(oss.str()); } -void DebugOverlay::draw(sf::RenderWindow &window) const { window.draw(m_text); } +void DebugOverlay::draw(sf::RenderWindow &window) const { window.draw(m_text); } \ No newline at end of file diff --git a/src/DebugOverlay.hpp b/src/DebugOverlay.hpp index 73e1050..8d6beba 100644 --- a/src/DebugOverlay.hpp +++ b/src/DebugOverlay.hpp @@ -19,4 +19,11 @@ class DebugOverlay { sf::Text m_text; sf::Clock m_fpsClock; float m_fps = 0.f; + float m_averageFrametime = 0.f; + float m_timeSinceLastAvgUpdate = 0.f; + float m_timeSinceLastUpdate = 0.f; + + static constexpr size_t FRAME_HISTORY_SIZE = 60; + std::array m_frameTimeHistory{}; + size_t m_currentFrameIndex = 0u; }; diff --git a/src/Game.cpp b/src/Game.cpp index 70a442a..4e7653b 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -25,7 +25,7 @@ Game::Game() m_threadPool(ThreadUtils::calculateSafeWorkerThreads()) { m_window.create(sf::VideoMode({Constants::WIDTH, Constants::HEIGHT}), "SFML Playground"); - m_window.setVerticalSyncEnabled(true); + m_window.setVerticalSyncEnabled(false); m_windowSize = sf::Vector2f(Constants::WIDTH, Constants::HEIGHT); m_objects.clear(); @@ -46,6 +46,8 @@ void Game::processKeyPressed(const sf::Event::KeyPressed &keyPressed) { case sf::Keyboard::Key::D: m_toggleDebug = !m_toggleDebug; break; + case sf::Keyboard::Key::Delete: + if (!m_objects.empty()) m_objects.pop_back(); default: break; } @@ -205,7 +207,7 @@ void Game::render() { if (!m_toggleDebug) continue; if (const auto *ball = dynamic_cast(object.get())) { - DebugDraw::addDirectionLine(m_debugLines, ball, m_window); + // DebugDraw::addDirectionLine(m_debugLines, ball, m_window); DebugDraw::addVelocityLine(m_debugLines, ball); } }