diff --git a/src/Balls.hpp b/src/Balls.hpp index bbe900f..1030885 100644 --- a/src/Balls.hpp +++ b/src/Balls.hpp @@ -1,140 +1,140 @@ #pragma once -#include -#include -#include - #include +#include +#include +#include +#include +namespace v1 { struct Ball { - sf::CircleShape shape; - sf::Vector2f velocity; + 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); - } + 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 balls; - std::random_device rd; - std::mt19937 gen; - std::uniform_real_distribution posDist; - std::uniform_real_distribution velDist; - std::uniform_int_distribution colorDist; - std::uniform_real_distribution radiusDist; + private: + // Create balls + std::vector balls; + std::random_device rd; + std::mt19937 gen; + std::uniform_real_distribution posDist; + std::uniform_real_distribution velDist; + std::uniform_int_distribution colorDist; + std::uniform_real_distribution radiusDist; -public: - BallGame::BallGame() { - gen = std::mt19937(rd()); - posDist = std::uniform_real_distribution(5.0f, 795.0f); - velDist = std::uniform_real_distribution(-200.0f, 200.0f); - colorDist = std::uniform_int_distribution(0, 255); - radiusDist = std::uniform_real_distribution(2.5f, 2.5f); + public: + BallGame() { + gen = std::mt19937(rd()); + posDist = std::uniform_real_distribution(5.0f, 795.0f); + velDist = std::uniform_real_distribution(-200.0f, 200.0f); + colorDist = std::uniform_int_distribution(0, 255); + radiusDist = std::uniform_real_distribution(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 - ); - } - } + // 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); - } + 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]; + // 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(); + 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; + // 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; + 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); + // 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; + // 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; + // 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; + // 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; - } - } - } + // 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(); + // 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)); - } - } + // 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)); - } - } - } - } + 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); - } - } -}; \ No newline at end of file + void drawBalls(sf::RenderWindow &window) const { + for (const auto &ball : balls) { + window.draw(ball.shape); + } + } +}; +} // namespace v1 diff --git a/src/collision_crisis.cpp b/src/collision_crisis.cpp index c257694..5c747ff 100644 --- a/src/collision_crisis.cpp +++ b/src/collision_crisis.cpp @@ -9,6 +9,13 @@ #include #include +#include "Balls.hpp" +namespace v1 { +static BallGame sim; +} +namespace v2 { +} + void configure(AppConfig &config) { config.window_title = "CHANGEME"; config.frame_rate_limit = std::nullopt; @@ -18,7 +25,6 @@ void configure(AppConfig &config) { void setup() { ImGui::GetIO().ConfigFlags |= (ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_DockingEnable); sf::View view{get_window().getView()}; - view.setCenter({0.f, 0.f}); set_render_view(view); } @@ -29,18 +35,17 @@ void handle_window_event(sf::Event const &event) { if (sf::Event::Resized const *resized{event.getIf()}) { sf::View view{get_window().getView()}; view.setSize({static_cast(resized->size.x), static_cast(resized->size.y)}); + view.setCenter({view.getSize().x / 2.f, view.getSize().y / 2.f}); set_render_view(view); } } void loop(double delta) { + v1::sim.updateBalls(get_window().getSize(), delta); } void draw_scene(sf::RenderTarget &target, sf::RenderStates const &states) { - static sf::RectangleShape rect{{300, 300}}; - sf::RenderStates n_states{states}; - n_states.transform.translate({-150, -150}); - target.draw(rect, n_states); + v1::sim.drawBalls(get_window()); } void draw_main_menu_bar() { diff --git a/src/defs.h b/src/defs.h index eab06ee..75ac1a3 100644 --- a/src/defs.h +++ b/src/defs.h @@ -10,8 +10,8 @@ #include struct AppConfig { - sf::String window_title{ "UNNAMED WINDOW" }; - sf::VideoMode mode{ { 1280, 720 } }; + sf::String window_title{"UNNAMED WINDOW"}; + sf::VideoMode mode{{1280, 720}}; sf::RenderStates default_render_states{sf::RenderStates::Default}; bool vsync{false}; std::optional frame_rate_limit{std::nullopt}; @@ -19,7 +19,7 @@ struct AppConfig { extern AppConfig const &get_application_configuration(); extern sf::Time const &get_delta_time(); -extern sf::RenderWindow const &get_window(); +extern sf::RenderWindow &get_window(); extern void set_render_view(sf::View const &view); #endif // !LLCS_DEFS_H diff --git a/src/main.cpp b/src/main.cpp index a0a9752..5542afb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,59 +13,59 @@ static sf::View view{}; extern void configure(AppConfig &config); void initialize_window() { - cfg = AppConfig(); - configure(cfg); - window.create(cfg.mode, cfg.window_title); - if (cfg.frame_rate_limit) - window.setFramerateLimit(cfg.frame_rate_limit.value_or(0)); - window.setVerticalSyncEnabled(cfg.vsync); - view = window.getDefaultView(); + cfg = AppConfig(); + configure(cfg); + window.create(cfg.mode, cfg.window_title); + if (cfg.frame_rate_limit) { + window.setFramerateLimit(cfg.frame_rate_limit.value_or(0)); + } + window.setVerticalSyncEnabled(cfg.vsync); + view = window.getDefaultView(); } void initialize_imgui() { - if (!ImGui::SFML::Init(window)) - exit(-1); + if (!ImGui::SFML::Init(window)) + exit(-1); } extern void handle_input_event(sf::Event const &evt); extern void handle_window_event(sf::Event const &evt); void try_handle_input_event(sf::Event const &event) { - bool const is_input_event{ - event.is() || event.is() || - event.is() || - event.is() || event.is() || - event.is() || event.is() || - event.is() || event.is() || - event.is() || - event.is() || event.is() || - event.is() || event.is() - }; - if (is_input_event) { - handle_input_event(event); - } + bool const is_input_event{ + event.is() || event.is() || + event.is() || + event.is() || event.is() || + event.is() || event.is() || + event.is() || event.is() || + event.is() || + event.is() || event.is() || + event.is() || event.is()}; + if (is_input_event) { + handle_input_event(event); + } } void try_handle_window_event(sf::Event const &event) { - bool const is_window_event{ - event.is() || - event.is() || - event.is() - }; - if (is_window_event) { - handle_window_event(event); - } + bool const is_window_event{ + event.is() || + event.is() || + event.is()}; + if (is_window_event) { + handle_window_event(event); + } } void poll_events() { - while (std::optional const event{ window.pollEvent() }) - { - ImGui::SFML::ProcessEvent(window, *event); - try_handle_input_event(*event); - try_handle_window_event(*event); + while (std::optional const event{window.pollEvent()}) { + ImGui::SFML::ProcessEvent(window, *event); + try_handle_input_event(*event); + try_handle_window_event(*event); - if (event->is()) { window.close(); } - } + if (event->is()) { + window.close(); + } + } } extern void setup(void); @@ -76,44 +76,44 @@ extern void draw_gui(void); extern void shutdown(void); int main() { - initialize_window(); - initialize_imgui(); - setup(); - while (window.isOpen()) { - // Event Polling - poll_events(); - // Update - delta_time = delta_clock.restart(); - ImGui::SFML::Update(window, delta_time); - loop(delta_time.asSeconds()); - if(ImGui::BeginMainMenuBar()) { - draw_main_menu_bar(); - ImGui::EndMainMenuBar(); - } - draw_gui(); - // Render - window.clear(); - draw_scene(window, cfg.default_render_states); - ImGui::SFML::Render(window); - window.display(); - } - shutdown(); - ImGui::SFML::Shutdown(); - return 0; + initialize_window(); + initialize_imgui(); + setup(); + while (window.isOpen()) { + // Event Polling + poll_events(); + // Update + delta_time = delta_clock.restart(); + ImGui::SFML::Update(window, delta_time); + loop(delta_time.asSeconds()); + if (ImGui::BeginMainMenuBar()) { + draw_main_menu_bar(); + ImGui::EndMainMenuBar(); + } + draw_gui(); + // Render + window.clear(); + draw_scene(window, cfg.default_render_states); + ImGui::SFML::Render(window); + window.display(); + } + shutdown(); + ImGui::SFML::Shutdown(); + return 0; } AppConfig const &get_application_configuration() { - return cfg; + return cfg; } sf::Time const &get_delta_time() { - return delta_time; + return delta_time; } -sf::RenderWindow const &get_window() { - return window; +sf::RenderWindow &get_window() { + return window; } void set_render_view(sf::View const &view) { - window.setView(view); + window.setView(view); }