feat: added reference implementation
This commit is contained in:
parent
461002939d
commit
841d08ef95
140
src/Balls.hpp
Normal file
140
src/Balls.hpp
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <random>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
struct Ball {
|
||||||
|
sf::CircleShape shape;
|
||||||
|
sf::Vector2f velocity;
|
||||||
|
|
||||||
|
Ball(float x, float y, float radius, sf::Color color, float vx, float vy) {
|
||||||
|
shape.setRadius(radius);
|
||||||
|
shape.setPosition(sf::Vector2f(x, y));
|
||||||
|
shape.setFillColor(color);
|
||||||
|
shape.setOrigin(sf::Vector2f(radius, radius)); // Center origin
|
||||||
|
velocity = sf::Vector2f(vx, vy);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BallGame {
|
||||||
|
private:
|
||||||
|
// Create balls
|
||||||
|
std::vector<Ball> balls;
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen;
|
||||||
|
std::uniform_real_distribution<float> posDist;
|
||||||
|
std::uniform_real_distribution<float> velDist;
|
||||||
|
std::uniform_int_distribution<int> colorDist;
|
||||||
|
std::uniform_real_distribution<float> radiusDist;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BallGame::BallGame() {
|
||||||
|
gen = std::mt19937(rd());
|
||||||
|
posDist = std::uniform_real_distribution<float>(5.0f, 795.0f);
|
||||||
|
velDist = std::uniform_real_distribution<float>(-200.0f, 200.0f);
|
||||||
|
colorDist = std::uniform_int_distribution<int>(0, 255);
|
||||||
|
radiusDist = std::uniform_real_distribution<float>(2.5f, 2.5f);
|
||||||
|
|
||||||
|
// Generate random balls
|
||||||
|
for (int i = 0; i < 2500; ++i) {
|
||||||
|
sf::Color randomColor(colorDist(gen), colorDist(gen), colorDist(gen));
|
||||||
|
balls.emplace_back(
|
||||||
|
posDist(gen), posDist(gen), // position
|
||||||
|
radiusDist(gen), // radius
|
||||||
|
randomColor, // color
|
||||||
|
velDist(gen), velDist(gen) // velocity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBalls(const sf::Vector2u& windowSize, float deltaTime) {
|
||||||
|
// Update positions
|
||||||
|
for (auto& ball : balls) {
|
||||||
|
ball.shape.move(ball.velocity * deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle ball-to-ball collisions
|
||||||
|
for (size_t i = 0; i < balls.size(); ++i) {
|
||||||
|
for (size_t j = i + 1; j < balls.size(); ++j) {
|
||||||
|
Ball& ball1 = balls[i];
|
||||||
|
Ball& ball2 = balls[j];
|
||||||
|
|
||||||
|
sf::Vector2f pos1 = ball1.shape.getPosition();
|
||||||
|
sf::Vector2f pos2 = ball2.shape.getPosition();
|
||||||
|
float radius1 = ball1.shape.getRadius();
|
||||||
|
float radius2 = ball2.shape.getRadius();
|
||||||
|
|
||||||
|
// Calculate distance between centers
|
||||||
|
sf::Vector2f delta = pos2 - pos1;
|
||||||
|
float distance = std::sqrt(delta.x * delta.x + delta.y * delta.y);
|
||||||
|
float minDistance = radius1 + radius2;
|
||||||
|
|
||||||
|
if (distance < minDistance && distance > 0) {
|
||||||
|
// Normalize collision vector
|
||||||
|
sf::Vector2f normal = delta / distance;
|
||||||
|
|
||||||
|
// Separate balls to prevent overlap
|
||||||
|
float overlap = minDistance - distance;
|
||||||
|
sf::Vector2f separation = normal * (overlap * 0.5f);
|
||||||
|
ball1.shape.setPosition(pos1 - separation);
|
||||||
|
ball2.shape.setPosition(pos2 + separation);
|
||||||
|
|
||||||
|
// Calculate relative velocity
|
||||||
|
sf::Vector2f relativeVel = ball2.velocity - ball1.velocity;
|
||||||
|
float velAlongNormal = relativeVel.x * normal.x + relativeVel.y * normal.y;
|
||||||
|
|
||||||
|
// Don't resolve if velocities are separating
|
||||||
|
if (velAlongNormal > 0) continue;
|
||||||
|
|
||||||
|
// Apply collision response (elastic collision)
|
||||||
|
float restitution = 0.0f; // Bounce factor (0 = no bounce, 1 = perfect bounce)
|
||||||
|
float impulse = -(1 + restitution) * velAlongNormal;
|
||||||
|
|
||||||
|
// Assume equal mass for simplicity
|
||||||
|
sf::Vector2f impulseVector = impulse * normal;
|
||||||
|
ball1.velocity -= impulseVector;
|
||||||
|
ball2.velocity += impulseVector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle wall collisions
|
||||||
|
for (auto& ball : balls) {
|
||||||
|
sf::Vector2f pos = ball.shape.getPosition();
|
||||||
|
float radius = ball.shape.getRadius();
|
||||||
|
|
||||||
|
// Bounce off walls
|
||||||
|
if (pos.x - radius <= 0 || pos.x + radius >= windowSize.x) {
|
||||||
|
ball.velocity.x = -ball.velocity.x;
|
||||||
|
// Clamp position to prevent sticking
|
||||||
|
if (pos.x - radius <= 0) {
|
||||||
|
ball.shape.setPosition(sf::Vector2f(radius, pos.y));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ball.shape.setPosition(sf::Vector2f(windowSize.x - radius, pos.y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos.y - radius <= 0 || pos.y + radius >= windowSize.y) {
|
||||||
|
ball.velocity.y = -ball.velocity.y;
|
||||||
|
// Clamp position to prevent sticking
|
||||||
|
if (pos.y - radius <= 0) {
|
||||||
|
ball.shape.setPosition(sf::Vector2f(pos.x, radius));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ball.shape.setPosition(sf::Vector2f(pos.x, windowSize.y - radius));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawBalls( sf::RenderWindow& window ) const
|
||||||
|
{
|
||||||
|
for (const auto& ball : balls) {
|
||||||
|
window.draw(ball.shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <print>
|
#include <print>
|
||||||
|
|
||||||
|
|
||||||
void configure(AppConfig &config) {
|
void configure(AppConfig &config) {
|
||||||
config.window_title = "CHANGEME";
|
config.window_title = "CHANGEME";
|
||||||
config.frame_rate_limit = std::nullopt;
|
config.frame_rate_limit = std::nullopt;
|
||||||
|
|
@ -17,11 +16,7 @@ void configure(AppConfig &config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
ImGui::GetIO().ConfigFlags |= (
|
ImGui::GetIO().ConfigFlags |= (ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_DockingEnable);
|
||||||
ImGuiConfigFlags_NavEnableKeyboard
|
|
||||||
| ImGuiConfigFlags_NavEnableGamepad
|
|
||||||
| ImGuiConfigFlags_DockingEnable
|
|
||||||
);
|
|
||||||
sf::View view{get_window().getView()};
|
sf::View view{get_window().getView()};
|
||||||
view.setCenter({0.f, 0.f});
|
view.setCenter({0.f, 0.f});
|
||||||
set_render_view(view);
|
set_render_view(view);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue