refac: rendering, debug overlay, & game mechanics

This commit is contained in:
Florian Sylvain
2025-05-14 00:26:21 +02:00
parent e25d32f8c6
commit 60c33a7965
8 changed files with 77 additions and 85 deletions
-39
View File
@@ -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
+9 -9
View File
@@ -69,15 +69,15 @@ void Ball::updateColor() {
constexpr float TRANSITION_SPEED = 0.05f;
sf::Color newColor;
newColor.r = static_cast<std::uint8_t>(static_cast<float>(currentColor.r) +
TRANSITION_SPEED *
(targetColor.r - currentColor.r));
newColor.g = static_cast<std::uint8_t>(static_cast<float>(currentColor.g) +
TRANSITION_SPEED *
(targetColor.g - currentColor.g));
newColor.b = static_cast<std::uint8_t>(static_cast<float>(currentColor.b) +
TRANSITION_SPEED *
(targetColor.b - currentColor.b));
newColor.r = static_cast<std::uint8_t>(
static_cast<float>(currentColor.r) +
TRANSITION_SPEED * static_cast<float>(targetColor.r - currentColor.r));
newColor.g = static_cast<std::uint8_t>(
static_cast<float>(currentColor.g) +
TRANSITION_SPEED * static_cast<float>(targetColor.g - currentColor.g));
newColor.b = static_cast<std::uint8_t>(
static_cast<float>(currentColor.b) +
TRANSITION_SPEED * static_cast<float>(targetColor.b - currentColor.b));
newColor.a = 255;
m_shape.setFillColor(newColor);
+16 -24
View File
@@ -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<float>(m_circleTexture.getSize().x);
const float ySize = static_cast<float>(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 {
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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,
+36 -6
View File
@@ -1,31 +1,61 @@
#include "DebugOverlay.hpp"
#include <iomanip>
#include <sstream>
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());
}
+7
View File
@@ -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<float, FRAME_HISTORY_SIZE> m_frameTimeHistory{};
size_t m_currentFrameIndex = 0u;
};
+4 -2
View File
@@ -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<Ball *>(object.get())) {
DebugDraw::addDirectionLine(m_debugLines, ball, m_window);
// DebugDraw::addDirectionLine(m_debugLines, ball, m_window);
DebugDraw::addVelocityLine(m_debugLines, ball);
}
}