From c341f6a44699d71b8b20e6b814274b30e43514c8 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Sat, 23 Nov 2024 22:07:15 +0100 Subject: added profiling test --- src/test/Profiling.cpp | 128 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/test/Profiling.cpp (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp new file mode 100644 index 0000000..9929288 --- /dev/null +++ b/src/test/Profiling.cpp @@ -0,0 +1,128 @@ +#include "system/ParticleSystem.h" +#include "system/PhysicsSystem.h" +#include "system/RenderSystem.h" +#include +#include +#include + +#define private public +#define protected public + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono_literals; +using namespace crepe; +using namespace testing; + +class CollisionHandler : public Script { +public: + int box_id; + + CollisionHandler(int box_id) { + this->box_id = box_id; + } + + bool on_collision(const CollisionEvent& ev) { + // test load? + return true; + } + + void init() { + subscribe([this](const CollisionEvent& ev) -> bool { + return this->on_collision(ev); + }); + } + void update() { + // Retrieve component from the same GameObject this script is on + } +}; + +class Profiling : public Test { +public: + ComponentManager mgr; + // Add system used for profling tests + CollisionSystem collision_sys{mgr}; + PhysicsSystem physics_sys{mgr}; + ParticleSystem particle_sys{mgr}; + RenderSystem render_sys{mgr}; + ScriptSystem script_sys{mgr}; + + // Store individual function timings + std::map timings; + + // Min and max gameobject that should and can be created + int min_gameobject_count = 100; + int max_gameobject_count = 100; + + void SetUp() override { + + GameObject do_not_use = mgr.new_object("DO_NOT_USE","",{0,0}); + do_not_use.add_component(Color::WHITE); + // initialize systems here: + //calls init + script_sys.update(); + //creates window + render_sys.update(); + } + + // Helper function to time an update call and store its duration + template + long long time_function(const std::string& name, Func&& func) { + auto start = std::chrono::steady_clock::now(); + func(); + auto end = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(end - start).count(); + timings[name] = duration; // Store the duration in microseconds + return duration; // Return the duration in microseconds + } + + // Run and profile all systems, return the total time in milliseconds + long long run_all_systems() { + long long total_microseconds = 0; + total_microseconds += time_function("PhysicsSystem", [&]() { physics_sys.update(); }); + total_microseconds += time_function("CollisionSystem", [&]() { collision_sys.update(); }); + total_microseconds += time_function("ParticleSystem", [&]() { particle_sys.update(); }); + total_microseconds += time_function("RenderSystem", [&]() { render_sys.update(); }); + return total_microseconds; + } + + // Print timings of all functions + void log_timings(long long total_time,int game_object_count) const { + std::stringstream ss; + ss << std::endl <<"Function timings:\n"; // Starting with a header + for (const auto& [name, duration] : timings) { + ss << name << " took " << duration / 1000.0 << " ms (" << duration << " µs). " << std::endl; + } + ss << "Total time: " << total_time / 1000.0 << "ms (" << total_time << " µs)" << std::endl; + ss << "Amount of gameobjects: " << game_object_count << std::endl; + // Use GTest INFO macro to print the accumulated log without extra newlines + GTEST_LOG_(INFO) << ss.str(); + } +}; + +TEST_F(Profiling, Profiling_example) { + int game_object_count = 0; + long long total_time = 0; + while (total_time < 16000) { + game_object_count++; + { + //define gameobject used for testing + GameObject gameobject = mgr.new_object("gameobject","",{0,0}); + } + total_time = run_all_systems(); + if(game_object_count >= max_gameobject_count) break; + } + log_timings(total_time,game_object_count); + EXPECT_GE(game_object_count, min_gameobject_count); +} -- cgit v1.2.3 From 86b1f2208214fdb207e7d0541a293625990016c4 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Sat, 23 Nov 2024 22:16:45 +0100 Subject: Added simple profling test --- src/test/Profiling.cpp | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 9929288..518d1c5 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -25,22 +25,14 @@ using namespace std::chrono_literals; using namespace crepe; using namespace testing; -class CollisionHandler : public Script { -public: - int box_id; - - CollisionHandler(int box_id) { - this->box_id = box_id; - } - - bool on_collision(const CollisionEvent& ev) { - // test load? +class TestScript : public Script { + bool oncollision(const CollisionEvent& test) { + Log::logf("Box {} script on_collision()", test.info.first.collider.game_object_id); return true; } - void init() { subscribe([this](const CollisionEvent& ev) -> bool { - return this->on_collision(ev); + return this->oncollision(ev); }); } void update() { @@ -115,11 +107,41 @@ TEST_F(Profiling, Profiling_example) { int game_object_count = 0; long long total_time = 0; while (total_time < 16000) { - game_object_count++; + { //define gameobject used for testing GameObject gameobject = mgr.new_object("gameobject","",{0,0}); } + + game_object_count++; + total_time = run_all_systems(); + if(game_object_count >= max_gameobject_count) break; + } + log_timings(total_time,game_object_count); + EXPECT_GE(game_object_count, min_gameobject_count); +} + +TEST_F(Profiling, Profiling_small_object_no_collision) { + int game_object_count = 0; + long long total_time = 0; + while (total_time < 16000) { + + { + //define gameobject used for testing + GameObject gameobject = mgr.new_object("gameobject","",{static_cast(game_object_count*2),0}); + gameobject.add_component(Rigidbody::Data{ + .body_type = Rigidbody::BodyType::STATIC, + .use_gravity = false, + }); + gameobject.add_component(vec2{0, 0}, 1, 1); + gameobject.add_component().set_script(); + Color color(0, 0, 0, 0); + gameobject.add_component( + make_shared("/home/jaro/crepe/asset/texture/green_square.png"), color, + FlipSettings{true, true}); + } + render_sys.update(); + game_object_count++; total_time = run_all_systems(); if(game_object_count >= max_gameobject_count) break; } -- cgit v1.2.3 From 08a3171b6bcc9a36ad89f04d2cdae406eb366a96 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Sat, 23 Nov 2024 22:19:34 +0100 Subject: change test data --- src/test/Profiling.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 518d1c5..d7a4f2e 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -55,7 +55,7 @@ public: // Min and max gameobject that should and can be created int min_gameobject_count = 100; - int max_gameobject_count = 100; + int max_gameobject_count = 1000; void SetUp() override { @@ -140,6 +140,7 @@ TEST_F(Profiling, Profiling_small_object_no_collision) { make_shared("/home/jaro/crepe/asset/texture/green_square.png"), color, FlipSettings{true, true}); } + render_sys.update(); game_object_count++; total_time = run_all_systems(); -- cgit v1.2.3 From 0b677b12d959e6320dc560edd093603ac7fbc55b Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Sat, 23 Nov 2024 22:26:06 +0100 Subject: added particle test --- src/test/Profiling.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index d7a4f2e..5cc70a4 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -121,7 +122,7 @@ TEST_F(Profiling, Profiling_example) { EXPECT_GE(game_object_count, min_gameobject_count); } -TEST_F(Profiling, Profiling_small_object_no_collision) { +TEST_F(Profiling, Profiling_small_object) { int game_object_count = 0; long long total_time = 0; while (total_time < 16000) { @@ -140,7 +141,49 @@ TEST_F(Profiling, Profiling_small_object_no_collision) { make_shared("/home/jaro/crepe/asset/texture/green_square.png"), color, FlipSettings{true, true}); } - + + render_sys.update(); + game_object_count++; + total_time = run_all_systems(); + if(game_object_count >= max_gameobject_count) break; + } + log_timings(total_time,game_object_count); + EXPECT_GE(game_object_count, min_gameobject_count); +} + +TEST_F(Profiling, Profiling_small_object_Particle_emitter) { + int game_object_count = 0; + long long total_time = 0; + while (total_time < 16000) { + + { + //define gameobject used for testing + GameObject gameobject = mgr.new_object("gameobject","",{static_cast(game_object_count*2),0}); + gameobject.add_component(Rigidbody::Data{ + .body_type = Rigidbody::BodyType::STATIC, + .use_gravity = false, + }); + gameobject.add_component(vec2{0, 0}, 1, 1); + gameobject.add_component().set_script(); + Color color(0, 0, 0, 0); + gameobject.add_component( + make_shared("/home/jaro/crepe/asset/texture/green_square.png"), color, + FlipSettings{true, true}); + Sprite & test_sprite = gameobject.add_component( + make_shared("/home/jaro/crepe/asset/texture/img.png"), color, FlipSettings{false, false}); + auto & test = gameobject.add_component(ParticleEmitter::Data{ + .max_particles = 100, + .emission_rate = 100, + .end_lifespan = 100000, + .boundary{ + .width = 1000, + .height = 1000, + .offset = vec2{0, 0}, + .reset_on_exit = false, + }, + .sprite = test_sprite, + }); + } render_sys.update(); game_object_count++; total_time = run_all_systems(); -- cgit v1.2.3 From ca03e1fc7f0dd3e97f319529b9f00e48860f6d94 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Mon, 25 Nov 2024 20:49:47 +0100 Subject: improved test --- src/test/Profiling.cpp | 104 +++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 50 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 5cc70a4..8283bba 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -26,6 +26,14 @@ using namespace std::chrono_literals; using namespace crepe; using namespace testing; + +/* +List of test cases with component settings/details +1. Minimal test creates gameobject without additonal components +2. Minimal 'Complex' gameobject. Has dynamic body without bounce and no collision handler +3. Minimal 'Complex' gameobject. Same as test 2 but with particle emitter +*/ + class TestScript : public Script { bool oncollision(const CollisionEvent& test) { Log::logf("Box {} script on_collision()", test.info.first.collider.game_object_id); @@ -43,6 +51,11 @@ class TestScript : public Script { class Profiling : public Test { public: + // config for test + const int min_gameobject_count = 100; + const int max_gameobject_count = 1000; + const std::chrono::microseconds duration = 16000us; + ComponentManager mgr; // Add system used for profling tests CollisionSystem collision_sys{mgr}; @@ -51,12 +64,11 @@ public: RenderSystem render_sys{mgr}; ScriptSystem script_sys{mgr}; - // Store individual function timings - std::map timings; + // Test data + std::map timings; + int game_object_count = 0; + std::chrono::microseconds total_time = 0us; - // Min and max gameobject that should and can be created - int min_gameobject_count = 100; - int max_gameobject_count = 1000; void SetUp() override { @@ -71,18 +83,18 @@ public: // Helper function to time an update call and store its duration template - long long time_function(const std::string& name, Func&& func) { + std::chrono::microseconds time_function(const std::string& name, Func&& func) { auto start = std::chrono::steady_clock::now(); func(); auto end = std::chrono::steady_clock::now(); - auto duration = std::chrono::duration_cast(end - start).count(); - timings[name] = duration; // Store the duration in microseconds - return duration; // Return the duration in microseconds + std::chrono::microseconds duration = std::chrono::duration_cast(end - start); + timings[name] = duration; + return duration; } // Run and profile all systems, return the total time in milliseconds - long long run_all_systems() { - long long total_microseconds = 0; + std::chrono::microseconds run_all_systems() { + std::chrono::microseconds total_microseconds = 0us; total_microseconds += time_function("PhysicsSystem", [&]() { physics_sys.update(); }); total_microseconds += time_function("CollisionSystem", [&]() { collision_sys.update(); }); total_microseconds += time_function("ParticleSystem", [&]() { particle_sys.update(); }); @@ -91,41 +103,36 @@ public: } // Print timings of all functions - void log_timings(long long total_time,int game_object_count) const { + void log_timings() const { std::stringstream ss; - ss << std::endl <<"Function timings:\n"; // Starting with a header - for (const auto& [name, duration] : timings) { - ss << name << " took " << duration / 1000.0 << " ms (" << duration << " µs). " << std::endl; - } - ss << "Total time: " << total_time / 1000.0 << "ms (" << total_time << " µs)" << std::endl; - ss << "Amount of gameobjects: " << game_object_count << std::endl; - // Use GTest INFO macro to print the accumulated log without extra newlines - GTEST_LOG_(INFO) << ss.str(); + ss << "\nFunction timings:\n"; + for (const auto& [name, duration] : timings) { + ss << name << " took " << duration.count() / 1000.0 << " ms (" << duration.count() << " µs).\n"; + } + ss << "Total time: " << this->total_time.count() / 1000.0 << " ms (" << this->total_time.count() << " µs)\n"; + ss << "Amount of gameobjects: " << game_object_count << "\n"; + GTEST_LOG_(INFO) << ss.str(); } }; -TEST_F(Profiling, Profiling_example) { - int game_object_count = 0; - long long total_time = 0; - while (total_time < 16000) { - +TEST_F(Profiling, Profiling_1) { + while (this->total_time < this->duration) { + { //define gameobject used for testing GameObject gameobject = mgr.new_object("gameobject","",{0,0}); } - game_object_count++; - total_time = run_all_systems(); - if(game_object_count >= max_gameobject_count) break; + this->game_object_count++; + this->total_time = run_all_systems(); + if(this->game_object_count >= this->max_gameobject_count) break; } - log_timings(total_time,game_object_count); - EXPECT_GE(game_object_count, min_gameobject_count); + log_timings(); + EXPECT_GE(this->game_object_count, this->min_gameobject_count); } -TEST_F(Profiling, Profiling_small_object) { - int game_object_count = 0; - long long total_time = 0; - while (total_time < 16000) { +TEST_F(Profiling, Profiling_2) { + while (this->total_time < this->duration) { { //define gameobject used for testing @@ -142,19 +149,16 @@ TEST_F(Profiling, Profiling_small_object) { FlipSettings{true, true}); } - render_sys.update(); - game_object_count++; - total_time = run_all_systems(); - if(game_object_count >= max_gameobject_count) break; + this->game_object_count++; + this->total_time = run_all_systems(); + if(this->game_object_count >= this->max_gameobject_count) break; } - log_timings(total_time,game_object_count); - EXPECT_GE(game_object_count, min_gameobject_count); + log_timings(); + EXPECT_GE(this->game_object_count, this->min_gameobject_count); } -TEST_F(Profiling, Profiling_small_object_Particle_emitter) { - int game_object_count = 0; - long long total_time = 0; - while (total_time < 16000) { +TEST_F(Profiling, Profiling_3) { + while (this->total_time < this->duration) { { //define gameobject used for testing @@ -172,7 +176,7 @@ TEST_F(Profiling, Profiling_small_object_Particle_emitter) { Sprite & test_sprite = gameobject.add_component( make_shared("/home/jaro/crepe/asset/texture/img.png"), color, FlipSettings{false, false}); auto & test = gameobject.add_component(ParticleEmitter::Data{ - .max_particles = 100, + .max_particles = 10, .emission_rate = 100, .end_lifespan = 100000, .boundary{ @@ -185,10 +189,10 @@ TEST_F(Profiling, Profiling_small_object_Particle_emitter) { }); } render_sys.update(); - game_object_count++; - total_time = run_all_systems(); - if(game_object_count >= max_gameobject_count) break; + this->game_object_count++; + this->total_time = run_all_systems(); + if(this->game_object_count >= this->max_gameobject_count) break; } - log_timings(total_time,game_object_count); - EXPECT_GE(game_object_count, min_gameobject_count); + log_timings(); + EXPECT_GE(this->game_object_count, this->min_gameobject_count); } -- cgit v1.2.3 From b6c69952a1747b1181c9b684f40cf3a3f8c79def Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Mon, 25 Nov 2024 21:45:52 +0100 Subject: added average --- src/test/Profiling.cpp | 54 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 11 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 8283bba..6b32805 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -51,10 +51,16 @@ class TestScript : public Script { class Profiling : public Test { public: - // config for test + // Config for test + // Minimum amount to let test pass const int min_gameobject_count = 100; - const int max_gameobject_count = 1000; + // Maximum amount to stop test + const int max_gameobject_count = 200; + // Amount of times a test runs to calculate average + const int average = 10; + // Maximum duration to stop test const std::chrono::microseconds duration = 16000us; + ComponentManager mgr; // Add system used for profling tests @@ -88,7 +94,7 @@ public: func(); auto end = std::chrono::steady_clock::now(); std::chrono::microseconds duration = std::chrono::duration_cast(end - start); - timings[name] = duration; + timings[name] += duration; return duration; } @@ -107,16 +113,23 @@ public: std::stringstream ss; ss << "\nFunction timings:\n"; for (const auto& [name, duration] : timings) { - ss << name << " took " << duration.count() / 1000.0 << " ms (" << duration.count() << " µs).\n"; + ss << name << " took " << duration.count() / 1000.0 / average << " ms (" << duration.count() / average << " µs).\n"; } - ss << "Total time: " << this->total_time.count() / 1000.0 << " ms (" << this->total_time.count() << " µs)\n"; + ss << "Total time: " << this->total_time.count() / 1000.0 / average << " ms (" << this->total_time.count() / average << " µs)\n"; ss << "Amount of gameobjects: " << game_object_count << "\n"; GTEST_LOG_(INFO) << ss.str(); } + + void clear_timings() { + for (auto& [key, value] : timings) { + value = std::chrono::microseconds(0); + } + } }; TEST_F(Profiling, Profiling_1) { - while (this->total_time < this->duration) { + while (this->total_time/this->average < this->duration) { + { //define gameobject used for testing @@ -124,7 +137,14 @@ TEST_F(Profiling, Profiling_1) { } this->game_object_count++; - this->total_time = run_all_systems(); + + this->total_time = 0us; + clear_timings(); + + for (int amount = 0; amount < this->average; amount++) { + this->total_time += run_all_systems(); + } + if(this->game_object_count >= this->max_gameobject_count) break; } log_timings(); @@ -132,7 +152,7 @@ TEST_F(Profiling, Profiling_1) { } TEST_F(Profiling, Profiling_2) { - while (this->total_time < this->duration) { + while (this->total_time/this->average < this->duration) { { //define gameobject used for testing @@ -150,7 +170,13 @@ TEST_F(Profiling, Profiling_2) { } this->game_object_count++; - this->total_time = run_all_systems(); + + this->total_time = 0us; + clear_timings(); + for (int amount = 0; amount < this->average; amount++) { + this->total_time += run_all_systems(); + } + if(this->game_object_count >= this->max_gameobject_count) break; } log_timings(); @@ -158,7 +184,7 @@ TEST_F(Profiling, Profiling_2) { } TEST_F(Profiling, Profiling_3) { - while (this->total_time < this->duration) { + while (this->total_time/this->average < this->duration) { { //define gameobject used for testing @@ -190,7 +216,13 @@ TEST_F(Profiling, Profiling_3) { } render_sys.update(); this->game_object_count++; - this->total_time = run_all_systems(); + + this->total_time = 0us; + clear_timings(); + for (int amount = 0; amount < this->average; amount++) { + this->total_time += run_all_systems(); + } + if(this->game_object_count >= this->max_gameobject_count) break; } log_timings(); -- cgit v1.2.3 From 15498a9b2b1c0052bcde6b367c1726b1d883cdd2 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Tue, 26 Nov 2024 19:38:26 +0100 Subject: added average --- src/test/Profiling.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 6b32805..59d9ed6 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -57,7 +57,7 @@ public: // Maximum amount to stop test const int max_gameobject_count = 200; // Amount of times a test runs to calculate average - const int average = 10; + const int average = 5; // Maximum duration to stop test const std::chrono::microseconds duration = 16000us; -- cgit v1.2.3 From 8f2d0a5a7edb6120c85cb7250e14e2055831a7cb Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Tue, 26 Nov 2024 19:42:09 +0100 Subject: fixed path --- src/test/Profiling.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 59d9ed6..2b03102 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -165,7 +165,7 @@ TEST_F(Profiling, Profiling_2) { gameobject.add_component().set_script(); Color color(0, 0, 0, 0); gameobject.add_component( - make_shared("/home/jaro/crepe/asset/texture/green_square.png"), color, + make_shared("asset/texture/green_square.png"), color, FlipSettings{true, true}); } @@ -197,10 +197,10 @@ TEST_F(Profiling, Profiling_3) { gameobject.add_component().set_script(); Color color(0, 0, 0, 0); gameobject.add_component( - make_shared("/home/jaro/crepe/asset/texture/green_square.png"), color, + make_shared("asset/texture/green_square.png"), color, FlipSettings{true, true}); Sprite & test_sprite = gameobject.add_component( - make_shared("/home/jaro/crepe/asset/texture/img.png"), color, FlipSettings{false, false}); + make_shared("asset/texture/img.png"), color, FlipSettings{false, false}); auto & test = gameobject.add_component(ParticleEmitter::Data{ .max_particles = 10, .emission_rate = 100, -- cgit v1.2.3 From 7566fa3d50093935315598aabcb0dc0a9e7cca57 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Sun, 1 Dec 2024 22:07:05 +0100 Subject: removed struct and renamed structs --- src/crepe/system/CollisionSystem.cpp | 100 ++++++++++++++-------------- src/crepe/system/CollisionSystem.h | 41 +++++------- src/test/CMakeLists.txt | 4 +- src/test/CollisionTest.cpp | 124 +++++++++++++++++------------------ src/test/Profiling.cpp | 2 +- 5 files changed, 134 insertions(+), 137 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 6f2c39d..362378d 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -28,19 +28,19 @@ void CollisionSystem::update() { std::vector> boxcolliders = mgr.get_components_by_type(); std::vector> circlecolliders = mgr.get_components_by_type(); - std::vector all_colliders; + std::vector all_colliders; // Add BoxCollider references for (auto& box : boxcolliders) { - all_colliders.push_back(collider_stor{box}); + all_colliders.push_back(collider_variant{box}); } // Add CircleCollider references for (auto& circle : circlecolliders) { - all_colliders.push_back(collider_stor{circle}); + all_colliders.push_back(collider_variant{circle}); } // Check between all colliders if there is a collision - std::vector> collided = check_collisions(all_colliders); + std::vector> collided = check_collisions(all_colliders); // For both objects call the collision handler for (auto& collision_pair : collided) { @@ -49,30 +49,30 @@ void CollisionSystem::update() { } } -void CollisionSystem::collision_handler_request(CollidedInfoStor& data1,CollidedInfoStor& data2){ +void CollisionSystem::collision_handler_request(CollisionInternal& data1,CollisionInternal& data2){ - ColliderStorType type = check_collider_type(data1.collider,data2.collider); - std::pair move_back_data = collision_handler(data1,data2,type); + CollisionInternalType type = check_collider_type(data1.collider,data2.collider); + std::pair resolution_data = collision_handler(data1,data2,type); OptionalRef collider1; OptionalRef collider2; switch (type) { - case ColliderStorType::BOX_BOX:{ + case CollisionInternalType::BOX_BOX:{ collider1 = std::get>(data1.collider); collider2 = std::get>(data2.collider); break; } - case ColliderStorType::BOX_CIRCLE:{ + case CollisionInternalType::BOX_CIRCLE:{ collider1 = std::get>(data1.collider); collider2 = std::get>(data2.collider); break; } - case ColliderStorType::CIRCLE_BOX:{ + case CollisionInternalType::CIRCLE_BOX:{ collider1 = std::get>(data1.collider); collider2 = std::get>(data2.collider); break; } - case ColliderStorType::CIRCLE_CIRCLE:{ + case CollisionInternalType::CIRCLE_CIRCLE:{ collider1 = std::get>(data1.collider); collider2 = std::get>(data2.collider); break; @@ -81,10 +81,14 @@ void CollisionSystem::collision_handler_request(CollidedInfoStor& data1,Collided // collision info crepe::CollisionSystem::CollisionInfo collision_info{ - .first={ collider1, data1.transform, data1.rigidbody }, - .second={ collider2, data2.transform, data2.rigidbody }, - .move_back_value = move_back_data.first, - .move_back_direction = move_back_data.second, + .first_collider = collider1, + .first_transform = data1.transform, + .first_rigidbody = data1.rigidbody, + .second_collider = collider2, + .second_transform = data2.transform, + .second_rigidbody = data2.rigidbody, + .resolution = resolution_data.first, + .resolution_direction = resolution_data.second, }; // Determine if static needs to be called @@ -92,23 +96,23 @@ void CollisionSystem::collision_handler_request(CollidedInfoStor& data1,Collided } -std::pair CollisionSystem::collision_handler(CollidedInfoStor& data1,CollidedInfoStor& data2,ColliderStorType type) { +std::pair CollisionSystem::collision_handler(CollisionInternal& data1,CollisionInternal& data2,CollisionInternalType type) { vec2 move_back; switch (type) { - case ColliderStorType::BOX_BOX: { + case CollisionInternalType::BOX_BOX: { const BoxCollider & collider1 = std::get>(data1.collider); const BoxCollider & collider2 = std::get>(data2.collider); vec2 collider_pos1 = current_position(collider1.offset, data1.transform, data1.rigidbody); vec2 collider_pos2 = current_position(collider2.offset, data2.transform, data2.rigidbody); move_back = box_box_move_back(collider1,collider2,collider_pos1,collider_pos2); } - case ColliderStorType::BOX_CIRCLE: { + case CollisionInternalType::BOX_CIRCLE: { } - case ColliderStorType::CIRCLE_CIRCLE: { + case CollisionInternalType::CIRCLE_CIRCLE: { } - case ColliderStorType::CIRCLE_BOX: { + case CollisionInternalType::CIRCLE_BOX: { } } @@ -165,43 +169,43 @@ vec2 CollisionSystem::box_box_move_back(const BoxCollider& box_collider1,const B void CollisionSystem::determine_collision_handler(CollisionInfo& info){ // Check rigidbody type for static - if(info.first.rigidbody.data.body_type != Rigidbody::BodyType::STATIC) + if(info.first_rigidbody.data.body_type != Rigidbody::BodyType::STATIC) { // If second body is static perform the static collision handler in this system - if(info.second.rigidbody.data.body_type == Rigidbody::BodyType::STATIC){ + if(info.second_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){ static_collision_handler(info); }; // Call collision event for user CollisionEvent data(info); - EventManager::get_instance().trigger_event(data, info.first.collider.game_object_id); + EventManager::get_instance().trigger_event(data, info.first_collider.game_object_id); } } void CollisionSystem::static_collision_handler(CollisionInfo& info){ // Move object back using calculate move back value - info.first.transform.position += info.move_back_value; + info.first_transform.position += info.resolution; // If bounce is enabled mirror velocity - if(info.first.rigidbody.data.bounce) { - if(info.move_back_direction == Direction::BOTH) + if(info.first_rigidbody.data.bounce) { + if(info.resolution_direction == Direction::BOTH) { - info.first.rigidbody.data.linear_velocity.y = -info.first.rigidbody.data.linear_velocity.y * info.first.rigidbody.data.elastisity; - info.first.rigidbody.data.linear_velocity.x = -info.first.rigidbody.data.linear_velocity.x * info.first.rigidbody.data.elastisity; + info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity; + info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity; } - else if(info.move_back_direction == Direction::Y_DIRECTION) { - info.first.rigidbody.data.linear_velocity.y = -info.first.rigidbody.data.linear_velocity.y * info.first.rigidbody.data.elastisity; + else if(info.resolution_direction == Direction::Y_DIRECTION) { + info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity; } - else if(info.move_back_direction == Direction::X_DIRECTION){ - info.first.rigidbody.data.linear_velocity.x = -info.first.rigidbody.data.linear_velocity.x * info.first.rigidbody.data.elastisity; + else if(info.resolution_direction == Direction::X_DIRECTION){ + info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity; } } // Stop movement if bounce is disabled else { - info.first.rigidbody.data.linear_velocity = {0,0}; + info.first_rigidbody.data.linear_velocity = {0,0}; } } -std::vector> CollisionSystem::check_collisions(std::vector & colliders) { +std::vector> CollisionSystem::check_collisions(std::vector & colliders) { // TODO: @@ -233,7 +237,7 @@ std::vector> collisions_ret; + std::vector> collisions_ret; for (size_t i = 0; i < colliders.size(); ++i) { std::visit([&](auto& inner_collider_ref) { if (!inner_collider_ref.get().active) return; @@ -245,11 +249,11 @@ std::vectorfirst.get(), inner_components->second.get()}, - CollidedInfoStor{colliders[j], outer_components->first.get(), outer_components->second.get()} + CollisionInternal{colliders[i], inner_components->first.get(), inner_components->second.get()}, + CollisionInternal{colliders[j], outer_components->first.get(), outer_components->second.get()} ); }, colliders[j]); } @@ -259,45 +263,45 @@ std::vector>(collider1)){ if(std::holds_alternative>(collider2)) { - return ColliderStorType::CIRCLE_CIRCLE; + return CollisionInternalType::CIRCLE_CIRCLE; } else { - return ColliderStorType::CIRCLE_BOX; + return CollisionInternalType::CIRCLE_BOX; } } else { if(std::holds_alternative>(collider2)) { - return ColliderStorType::BOX_CIRCLE; + return CollisionInternalType::BOX_CIRCLE; } else { - return ColliderStorType::BOX_BOX; + return CollisionInternalType::BOX_BOX; } } } -bool CollisionSystem::check_collision(const collider_stor& collider1,std::pair, std::reference_wrapper> components1,const collider_stor& collider2,std::pair, std::reference_wrapper> components2, ColliderStorType type){ +bool CollisionSystem::check_collision(const collider_variant& collider1,std::pair, std::reference_wrapper> components1,const collider_variant& collider2,std::pair, std::reference_wrapper> components2, CollisionInternalType type){ switch (type) { - case ColliderStorType::BOX_BOX: { + case CollisionInternalType::BOX_BOX: { const BoxCollider & box_collider1 = std::get>(collider1); const BoxCollider & box_collider2 = std::get>(collider2); return check_box_box_collision(box_collider1,box_collider2,components1.first.get(),components2.first.get(),components1.second.get(),components2.second.get()); } - case ColliderStorType::BOX_CIRCLE: { + case CollisionInternalType::BOX_CIRCLE: { const BoxCollider & box_collider = std::get>(collider1); const CircleCollider & circle_collider = std::get>(collider2); return check_box_circle_collision(box_collider,circle_collider,components1.first.get(),components2.first.get(),components1.second.get(),components2.second.get()); } - case ColliderStorType::CIRCLE_CIRCLE: { + case CollisionInternalType::CIRCLE_CIRCLE: { const CircleCollider & circle_collider1 = std::get>(collider1); const CircleCollider & circle_collider2 = std::get>(collider2); return check_circle_circle_collision(circle_collider1,circle_collider2,components1.first.get(),components2.first.get(),components1.second.get(),components2.second.get()); } - case ColliderStorType::CIRCLE_BOX: { + case CollisionInternalType::CIRCLE_BOX: { const CircleCollider & circle_collider = std::get>(collider1); const BoxCollider & box_collider = std::get>(collider2); return check_box_circle_collision(box_collider,circle_collider,components1.first.get(),components2.first.get(),components1.second.get(),components2.second.get()); diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 6334ba1..f8c7633 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -23,10 +23,10 @@ private: //! A variant type that can hold either a BoxCollider or a CircleCollider. // using collider_stor = std::variant; - using collider_stor = std::variant, std::reference_wrapper>; + using collider_variant = std::variant, std::reference_wrapper>; //! A enum that is used to tell the pair of the collider stor in a std::pair. - enum class ColliderStorType { + enum class CollisionInternalType { BOX_BOX, CIRCLE_CIRCLE, BOX_CIRCLE, @@ -38,9 +38,9 @@ private: * * This structure stores the collider type, its associated transform, and its rigidbody. */ - struct CollidedInfoStor { + struct CollisionInternal { //! Store either BoxCollider or CircleCollider - collider_stor& collider; + collider_variant& collider; Transform& transform; Rigidbody& rigidbody; }; @@ -54,27 +54,20 @@ private: }; public: - /** - * \brief A structure representing the collision information between two colliders. - * - * This structure contains both colliders, their associated transforms and rigidbodies, - * as well as the movement vector to resolve the collision. - */ - struct ColliderInfo { - const Collider& collider; - Transform& transform; - Rigidbody& rigidbody; - }; /** * \brief A structure representing detailed collision information between two colliders. * * This includes the movement data required to resolve the collision. */ struct CollisionInfo{ - ColliderInfo first; - ColliderInfo second; - vec2 move_back_value; - Direction move_back_direction = Direction::NONE; + Collider& first_collider; + Transform& first_transform; + Rigidbody& first_rigidbody; + Collider& second_collider; + Transform& second_transform; + Rigidbody& second_rigidbody; + vec2 resolution; + Direction resolution_direction = Direction::NONE; }; public: @@ -94,7 +87,7 @@ private: //generic * * \return collider pair type. */ - ColliderStorType check_collider_type(const collider_stor& collider1,const collider_stor& collider2); + CollisionInternalType check_collider_type(const collider_variant& collider1,const collider_variant& collider2); /** * \brief Calculates the position of the Collider @@ -122,7 +115,7 @@ private:// handeling * * \return Postion of collider. */ - void collision_handler_request(CollidedInfoStor& data1,CollidedInfoStor& data2); + void collision_handler_request(CollisionInternal& data1,CollisionInternal& data2); /** * \brief Calculates the move back value and direction of the Collision @@ -135,7 +128,7 @@ private:// handeling * * \return Move back value and direction for first gameobject */ - std::pair collision_handler(CollidedInfoStor& data1,CollidedInfoStor& data2 ,ColliderStorType type); + std::pair collision_handler(CollisionInternal& data1,CollisionInternal& data2 ,CollisionInternalType type); /** * \brief Calculates the move back value for box box collision @@ -183,7 +176,7 @@ private: // detection * * \return Move back value and direction for first gameobject */ - std::vector> check_collisions(std::vector & colliders); + std::vector> check_collisions(std::vector & colliders); /** * \brief Calls the correct check collision function. @@ -198,7 +191,7 @@ private: // detection * * \return status of collision */ - bool check_collision(const collider_stor& collider1,std::pair, std::reference_wrapper> components1,const collider_stor& collider2,std::pair, std::reference_wrapper> components2,CollisionSystem::ColliderStorType type); + bool check_collision(const collider_variant& collider1,std::pair, std::reference_wrapper> components1,const collider_variant& collider2,std::pair, std::reference_wrapper> components2,CollisionSystem::CollisionInternalType type); /** * \brief Check collision for box on box collider diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 68fa01c..616e238 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,5 +1,5 @@ target_sources(test_main PUBLIC - # CollisionTest.cpp + CollisionTest.cpp main.cpp # PhysicsTest.cpp # ScriptTest.cpp @@ -13,5 +13,5 @@ target_sources(test_main PUBLIC # ValueBrokerTest.cpp # DBTest.cpp # Vector2Test.cpp - Profiling.cpp + # Profiling.cpp ) diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index 245cced..8daf77f 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -114,11 +114,11 @@ TEST_F(CollisionTest, collision_example) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 2); + EXPECT_EQ(ev.info.first_collider.game_object_id, 2); }; EXPECT_FALSE(collision_happend); collision_sys.update(); @@ -129,17 +129,17 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, 10); - EXPECT_EQ(ev.info.move_back_value.y, 10); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::BOTH); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, 10); + EXPECT_EQ(ev.info.resolution.y, 10); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 2); - EXPECT_EQ(ev.info.move_back_value.x, 10); - EXPECT_EQ(ev.info.move_back_value.y, 10); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::BOTH); + EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.resolution.x, 10); + EXPECT_EQ(ev.info.resolution.y, 10); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); @@ -152,17 +152,17 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, -5); - EXPECT_EQ(ev.info.move_back_value.y, 0); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, -5); + EXPECT_EQ(ev.info.resolution.y, 0); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 2); - EXPECT_EQ(ev.info.move_back_value.x, 5); - EXPECT_EQ(ev.info.move_back_value.y, 0); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.resolution.x, 5); + EXPECT_EQ(ev.info.resolution.y, 0); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); @@ -175,17 +175,17 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, 0); - EXPECT_EQ(ev.info.move_back_value.y, -5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, 0); + EXPECT_EQ(ev.info.resolution.y, -5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 2); - EXPECT_EQ(ev.info.move_back_value.x, 0); - EXPECT_EQ(ev.info.move_back_value.y, 5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.resolution.x, 0); + EXPECT_EQ(ev.info.resolution.y, 5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); @@ -198,17 +198,17 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, 10); - EXPECT_EQ(ev.info.move_back_value.y, 10); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::BOTH); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, 10); + EXPECT_EQ(ev.info.resolution.y, 10); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 2); - EXPECT_EQ(ev.info.move_back_value.x, 10); - EXPECT_EQ(ev.info.move_back_value.y, 10); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::BOTH); + EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.resolution.x, 10); + EXPECT_EQ(ev.info.resolution.y, 10); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); @@ -225,17 +225,17 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, -5); - EXPECT_EQ(ev.info.move_back_value.y, -5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, -5); + EXPECT_EQ(ev.info.resolution.y, -5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 2); - EXPECT_EQ(ev.info.move_back_value.x, 5); - EXPECT_EQ(ev.info.move_back_value.y, 5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.resolution.x, 5); + EXPECT_EQ(ev.info.resolution.y, 5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); @@ -252,17 +252,17 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, -5); - EXPECT_EQ(ev.info.move_back_value.y, -5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, -5); + EXPECT_EQ(ev.info.resolution.y, -5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 2); - EXPECT_EQ(ev.info.move_back_value.x, 5); - EXPECT_EQ(ev.info.move_back_value.y, 5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.resolution.x, 5); + EXPECT_EQ(ev.info.resolution.y, 5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); @@ -280,10 +280,10 @@ TEST_F(CollisionTest, collision_box_box_static_both) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, 10); - EXPECT_EQ(ev.info.move_back_value.y, 10); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::BOTH); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, 10); + EXPECT_EQ(ev.info.resolution.y, 10); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { // is static should not be called @@ -302,10 +302,10 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, -5); - EXPECT_EQ(ev.info.move_back_value.y, -5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, -5); + EXPECT_EQ(ev.info.resolution.y, -5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { // is static should not be called @@ -326,10 +326,10 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first.collider.game_object_id, 1); - EXPECT_EQ(ev.info.move_back_value.x, -5); - EXPECT_EQ(ev.info.move_back_value.y, -5); - EXPECT_EQ(ev.info.move_back_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.resolution.x, -5); + EXPECT_EQ(ev.info.resolution.y, -5); + EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { // is static should not be called diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 2b03102..2549c57 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -36,7 +36,7 @@ List of test cases with component settings/details class TestScript : public Script { bool oncollision(const CollisionEvent& test) { - Log::logf("Box {} script on_collision()", test.info.first.collider.game_object_id); + Log::logf("Box {} script on_collision()", test.info.first_collider.game_object_id); return true; } void init() { -- cgit v1.2.3 From eeb66130e2cb94c94e1748576f98f78ce0f1ee86 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Mon, 2 Dec 2024 17:17:21 +0100 Subject: changed some values because of feedback and merged from master --- src/crepe/Collider.cpp | 2 +- src/crepe/Collider.h | 2 +- src/crepe/api/BoxCollider.cpp | 2 +- src/crepe/api/BoxCollider.h | 2 +- src/crepe/api/CircleCollider.cpp | 2 +- src/crepe/api/CircleCollider.h | 2 +- src/crepe/api/Rigidbody.h | 14 +++++------- src/crepe/system/CollisionSystem.cpp | 18 ++++++++-------- src/crepe/system/CollisionSystem.h | 8 +++---- src/crepe/system/PhysicsSystem.cpp | 10 ++++----- src/test/CMakeLists.txt | 2 +- src/test/CollisionTest.cpp | 5 ----- src/test/Profiling.cpp | 42 +++++++++++++++++++----------------- 13 files changed, 52 insertions(+), 59 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp index 80a944d..9d94152 100644 --- a/src/crepe/Collider.cpp +++ b/src/crepe/Collider.cpp @@ -2,4 +2,4 @@ using namespace crepe; -Collider::Collider(game_object_id_t id, vec2 offset) : Component(id), offset(offset) {} +Collider::Collider(game_object_id_t id, const vec2& offset) : Component(id), offset(offset) {} diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index e1624b4..15d3a24 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -7,7 +7,7 @@ namespace crepe { class Collider : public Component { public: - Collider(game_object_id_t id, vec2 offset); + Collider(game_object_id_t id, const vec2& offset); public: //! Offset of the collider relative to rigidbody position diff --git a/src/crepe/api/BoxCollider.cpp b/src/crepe/api/BoxCollider.cpp index 6034837..1069e90 100644 --- a/src/crepe/api/BoxCollider.cpp +++ b/src/crepe/api/BoxCollider.cpp @@ -4,4 +4,4 @@ using namespace crepe; -BoxCollider::BoxCollider(game_object_id_t game_object_id,vec2 offset, float width, float height) : Collider(game_object_id,offset), width(width), height(height) {} +BoxCollider::BoxCollider(game_object_id_t game_object_id,const vec2& offset, float width, float height) : Collider(game_object_id,offset), width(width), height(height) {} diff --git a/src/crepe/api/BoxCollider.h b/src/crepe/api/BoxCollider.h index 2ce1ee8..c83d54a 100644 --- a/src/crepe/api/BoxCollider.h +++ b/src/crepe/api/BoxCollider.h @@ -12,7 +12,7 @@ namespace crepe { */ class BoxCollider : public Collider { public: - BoxCollider(game_object_id_t game_object_id,vec2 offset, float width, float height); + BoxCollider(game_object_id_t game_object_id,const vec2& offset, float width, float height); //! Width of box collider float width; diff --git a/src/crepe/api/CircleCollider.cpp b/src/crepe/api/CircleCollider.cpp index 497ebba..473734e 100644 --- a/src/crepe/api/CircleCollider.cpp +++ b/src/crepe/api/CircleCollider.cpp @@ -3,4 +3,4 @@ using namespace crepe; -CircleCollider::CircleCollider(game_object_id_t game_object_id,vec2 offset, float radius) : Collider(game_object_id,offset), radius(radius) {} +CircleCollider::CircleCollider(game_object_id_t game_object_id,const vec2& offset, float radius) : Collider(game_object_id,offset), radius(radius) {} diff --git a/src/crepe/api/CircleCollider.h b/src/crepe/api/CircleCollider.h index c61f027..bbcc330 100644 --- a/src/crepe/api/CircleCollider.h +++ b/src/crepe/api/CircleCollider.h @@ -14,7 +14,7 @@ namespace crepe { class CircleCollider : public Collider { public: - CircleCollider(game_object_id_t game_object_id,vec2 offset, float radius); + CircleCollider(game_object_id_t game_object_id,const vec2& offset, float radius); //! Radius of the circle collider. float radius; diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 446c5dd..63b1b51 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -54,7 +54,7 @@ public: //! objects mass float mass = 0.0; //! gravtiy scale - float gravity_scale = 0.0; + float gravity_scale = 0; //! Changes if physics apply BodyType body_type = BodyType::DYNAMIC; //! linear velocity of object @@ -62,20 +62,16 @@ public: //! maximum linear velocity of object vec2 max_linear_velocity = {INFINITY ,INFINITY}; //! linear damping of object - vec2 linear_damping; + vec2 linear_velocity_factor; //! angular velocity of object - float angular_velocity = 0.0; + float angular_velocity = 1; //! max angular velocity of object float max_angular_velocity = INFINITY; //! angular damping of object - float angular_damping = 0.0; + float angular_velocity_factor = 1; //! movements constraints of object PhysicsConstraints constraints; - //! if gravity applies - bool use_gravity = true; - //! if object bounces - bool bounce = false; - //! bounce factor of material + //! bounce factor of material. 0.0 <= means all velocity is lost, 1.0 means it gets the same momentum but the mirrored direction. 0.5 is half of the velocity is saved. float elastisity = 0.0; //! offset of all colliders relative to transform position vec2 offset; diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 2fe3621..fbb16e8 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -146,10 +146,10 @@ std::pair CollisionSystem::collision_handler(Co resolution.x = data1.rigidbody.data.linear_velocity.x * (resolution.y/data1.rigidbody.data.linear_velocity.y); } - return {resolution,resolution_direction}; + return std::make_pair(resolution,resolution_direction); } -vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,vec2 final_position1,vec2 final_position2) const +vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,const vec2& final_position1,const vec2& final_position2) const { vec2 resolution; // Default resolution vector vec2 delta = final_position2 - final_position1; @@ -183,7 +183,7 @@ vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,co return resolution; } -vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, vec2 final_position1, vec2 final_position2) const +vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, const vec2& final_position1, const vec2& final_position2) const { vec2 delta = final_position2 - final_position1; @@ -205,7 +205,7 @@ vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider& circle_ return resolution; } -vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, vec2 circle_position, vec2 box_position) const +vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, const vec2& circle_position, const vec2& box_position) const { vec2 delta = circle_position - box_position; @@ -252,7 +252,7 @@ void CollisionSystem::static_collision_handler(CollisionInfo& info){ info.first_transform.position += info.resolution; // If bounce is enabled mirror velocity - if(info.first_rigidbody.data.bounce) { + if(info.first_rigidbody.data.elastisity > 0) { if(info.resolution_direction == Direction::BOTH) { info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity; @@ -335,12 +335,12 @@ CollisionSystem::get_active_transform_and_rigidbody(game_object_id_t game_object RefVector transforms = this->component_manager.get_components_by_id(game_object_id); if (transforms.empty()) return std::nullopt; + Transform& transform = transforms.front().get(); + if (!transform.active) return std::nullopt; + RefVector rigidbodies = this->component_manager.get_components_by_id(game_object_id); if (rigidbodies.empty()) return std::nullopt; - Transform& transform = transforms.front().get(); - if (!transform.active) return std::nullopt; - Rigidbody& rigidbody = rigidbodies.front().get(); if (!rigidbody.active) return std::nullopt; @@ -453,7 +453,7 @@ bool CollisionSystem::get_circle_circle_collision(const CircleCollider& circle1, return distance_squared <= radius_sum * radius_sum; } -vec2 CollisionSystem::get_current_position(vec2 collider_offset, const Transform& transform, const Rigidbody& rigidbody) const { +vec2 CollisionSystem::get_current_position(const vec2& collider_offset, const Transform& transform, const Rigidbody& rigidbody) const { // Get the rotation in radians float radians1 = transform.rotation * (M_PI / 180.0); diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 3f24db1..34c03ae 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -104,7 +104,7 @@ private: * \param rigidbody The Rigidbody of the associated game object. * \return The calculated position of the collider. */ - vec2 get_current_position(vec2 collider_offset, const Transform& transform, const Rigidbody& rigidbody) const; + vec2 get_current_position(const vec2& collider_offset, const Transform& transform, const Rigidbody& rigidbody) const; private: @@ -141,7 +141,7 @@ private: * \param position2 The position of the second BoxCollider. * \return The resolution vector for the collision. */ - vec2 get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,vec2 position1,vec2 position2) const; + vec2 get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,const vec2& position1,const vec2& position2) const; /** * \brief Calculates the resolution vector for two CircleCollider. @@ -154,7 +154,7 @@ private: * \param position2 The position of the second CircleCollider. * \return The resolution vector for the collision. */ - vec2 get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, vec2 final_position1, vec2 final_position2) const; + vec2 get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, const vec2& final_position1, const vec2& final_position2) const; /** * \brief Calculates the resolution vector for two CircleCollider. @@ -167,7 +167,7 @@ private: * \param box_position The position of the BocCollider. * \return The resolution vector for the collision. */ - vec2 get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, vec2 circle_position, vec2 box_position) const; + vec2 get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, const vec2& circle_position, const vec2& box_position) const; /** * \brief Determines the appropriate collision handler for a collision. diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index 514a4b3..8f21727 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -25,17 +25,17 @@ void PhysicsSystem::update() { if (transform.game_object_id == rigidbody.game_object_id) { // Add gravity - if (rigidbody.data.use_gravity) { + if (rigidbody.data.gravity_scale > 0) { rigidbody.data.linear_velocity.y += (rigidbody.data.mass * rigidbody.data.gravity_scale * gravity); } // Add damping - if (rigidbody.data.angular_damping != 0) { - rigidbody.data.angular_velocity *= rigidbody.data.angular_damping; + if (rigidbody.data.angular_velocity_factor != 1 && rigidbody.data.angular_velocity_factor > 0) { + rigidbody.data.angular_velocity *= rigidbody.data.angular_velocity_factor; } - if (rigidbody.data.linear_damping != vec2{0, 0}) { - rigidbody.data.linear_velocity *= rigidbody.data.linear_damping; + if (rigidbody.data.linear_velocity_factor != vec2{1, 1} && rigidbody.data.linear_velocity_factor.x > 0 && rigidbody.data.linear_velocity_factor.y > 0) { + rigidbody.data.linear_velocity *= rigidbody.data.linear_velocity_factor; } // Max velocity check diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 616e238..4555c0b 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -13,5 +13,5 @@ target_sources(test_main PUBLIC # ValueBrokerTest.cpp # DBTest.cpp # Vector2Test.cpp - # Profiling.cpp + Profiling.cpp ) diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index ed40b1b..92ff7ba 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -65,7 +65,6 @@ public: world.add_component(Rigidbody::Data{ // TODO: remove unrelated properties: .body_type = Rigidbody::BodyType::STATIC, - .bounce = false, .offset = {0,0}, }); // Create a box with an inner size of 10x10 units @@ -80,8 +79,6 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {0,0}, .constraints = {0, 0, 0}, - .use_gravity = true, - .bounce = true, .elastisity = 1, .offset = {0,0}, }); @@ -96,8 +93,6 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {0,0}, .constraints = {0, 0, 0}, - .use_gravity = true, - .bounce = true, .elastisity = 1, .offset = {0,0}, }); diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 2549c57..a88bf85 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -79,7 +79,8 @@ public: void SetUp() override { GameObject do_not_use = mgr.new_object("DO_NOT_USE","",{0,0}); - do_not_use.add_component(Color::WHITE); + do_not_use.add_component(Color::WHITE, ivec2{1080, 720}, + vec2{2000, 2000}, 1.0f); // initialize systems here: //calls init script_sys.update(); @@ -110,14 +111,19 @@ public: // Print timings of all functions void log_timings() const { - std::stringstream ss; - ss << "\nFunction timings:\n"; - for (const auto& [name, duration] : timings) { - ss << name << " took " << duration.count() / 1000.0 / average << " ms (" << duration.count() / average << " µs).\n"; - } - ss << "Total time: " << this->total_time.count() / 1000.0 / average << " ms (" << this->total_time.count() / average << " µs)\n"; - ss << "Amount of gameobjects: " << game_object_count << "\n"; - GTEST_LOG_(INFO) << ss.str(); + std::string result = "\nFunction timings:\n"; + + for (const auto& [name, duration] : timings) { + result += name + " took " + std::to_string(duration.count() / 1000.0 / average) + " ms (" + + std::to_string(duration.count() / average) + " µs).\n"; + } + + result += "Total time: " + std::to_string(this->total_time.count() / 1000.0 / average) + " ms (" + + std::to_string(this->total_time.count() / average) + " µs)\n"; + + result += "Amount of gameobjects: " + std::to_string(game_object_count) + "\n"; + + GTEST_LOG_(INFO) << result; } void clear_timings() { @@ -158,15 +164,14 @@ TEST_F(Profiling, Profiling_2) { //define gameobject used for testing GameObject gameobject = mgr.new_object("gameobject","",{static_cast(game_object_count*2),0}); gameobject.add_component(Rigidbody::Data{ - .body_type = Rigidbody::BodyType::STATIC, - .use_gravity = false, + .gravity_scale = 0.0, + .body_type = Rigidbody::BodyType::STATIC, }); gameobject.add_component(vec2{0, 0}, 1, 1); gameobject.add_component().set_script(); Color color(0, 0, 0, 0); - gameobject.add_component( - make_shared("asset/texture/green_square.png"), color, - FlipSettings{true, true}); + auto img = Texture("asset/texture/green_square.png"); + Sprite & test_sprite = gameobject.add_component(img, color, Sprite::FlipSettings{false, false}, 1, 1, 500); } this->game_object_count++; @@ -190,17 +195,14 @@ TEST_F(Profiling, Profiling_3) { //define gameobject used for testing GameObject gameobject = mgr.new_object("gameobject","",{static_cast(game_object_count*2),0}); gameobject.add_component(Rigidbody::Data{ + .gravity_scale = 0, .body_type = Rigidbody::BodyType::STATIC, - .use_gravity = false, }); gameobject.add_component(vec2{0, 0}, 1, 1); gameobject.add_component().set_script(); Color color(0, 0, 0, 0); - gameobject.add_component( - make_shared("asset/texture/green_square.png"), color, - FlipSettings{true, true}); - Sprite & test_sprite = gameobject.add_component( - make_shared("asset/texture/img.png"), color, FlipSettings{false, false}); + auto img = Texture("asset/texture/green_square.png"); + Sprite & test_sprite = gameobject.add_component(img, color, Sprite::FlipSettings{false, false}, 1, 1, 500); auto & test = gameobject.add_component(ParticleEmitter::Data{ .max_particles = 10, .emission_rate = 100, -- cgit v1.2.3 From 4bbc27098d5a8907ab0500ad3ccc82283cf95ddf Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Mon, 2 Dec 2024 20:34:00 +0100 Subject: merge fix and review fix --- src/example/game.cpp | 13 ++++--------- src/test/CMakeLists.txt | 24 ++++++++++++------------ src/test/PhysicsTest.cpp | 10 ++++------ src/test/Profiling.cpp | 10 +--------- 4 files changed, 21 insertions(+), 36 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/example/game.cpp b/src/example/game.cpp index e851526..c439f5d 100644 --- a/src/example/game.cpp +++ b/src/example/game.cpp @@ -18,7 +18,7 @@ using namespace std; class MyScript : public Script { bool oncollision(const CollisionEvent& test) { - Log::logf("Box {} script on_collision()", test.info.first.collider.game_object_id); + Log::logf("Box {} script on_collision()", test.info.first_collider.game_object_id); return true; } void init() { @@ -50,8 +50,6 @@ public: .gravity_scale = 0, .body_type = Rigidbody::BodyType::STATIC, .constraints = {0, 0, 0}, - .use_gravity = false, - .bounce = false, .offset = {0,0} }); world.add_component(vec2{0, 0-(screen_size_height/2+world_collider/2)}, world_collider, world_collider);; // Top @@ -67,17 +65,14 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {1,1}, .constraints = {0, 0, 0}, - .use_gravity = true, - .bounce = true, .elastisity = 1, .offset = {0,0}, }); game_object1.add_component(vec2{0, 0}, 20, 20); game_object1.add_component().set_script(); - game_object1.add_component( - make_shared("/home/jaro/crepe/asset/texture/green_square.png"), color, - FlipSettings{true, true}); - game_object1.add_component(Color::WHITE); + auto img = Texture("asset/texture/green_square.png"); + game_object1.add_component(img, color, Sprite::FlipSettings{false, false}, 1, 1, 500); + game_object1.add_component(Color::WHITE, ivec2{1080, 720},vec2{2000, 2000}, 1.0f); } string get_name() const { return "scene1"; } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 4555c0b..cd61fb7 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,17 +1,17 @@ target_sources(test_main PUBLIC CollisionTest.cpp main.cpp - # PhysicsTest.cpp - # ScriptTest.cpp - # ParticleTest.cpp - # AssetTest.cpp - # OptionalRefTest.cpp - # RenderSystemTest.cpp - # EventTest.cpp - # ECSTest.cpp - # SceneManagerTest.cpp - # ValueBrokerTest.cpp - # DBTest.cpp - # Vector2Test.cpp + PhysicsTest.cpp + ScriptTest.cpp + ParticleTest.cpp + AssetTest.cpp + OptionalRefTest.cpp + RenderSystemTest.cpp + EventTest.cpp + ECSTest.cpp + SceneManagerTest.cpp + ValueBrokerTest.cpp + DBTest.cpp + Vector2Test.cpp Profiling.cpp ) diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 33b6020..5dd448f 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -28,8 +28,6 @@ public: .max_linear_velocity = vec2{10, 10}, .max_angular_velocity = 10, .constraints = {0, 0}, - .use_gravity = true, - .bounce = false, }); } transforms = mgr.get_components_by_id(0); @@ -105,16 +103,16 @@ TEST_F(PhysicsTest, movement) { EXPECT_EQ(transform.position.y, 1); EXPECT_EQ(transform.rotation, 1); - rigidbody.data.linear_damping.x = 0.5; - rigidbody.data.linear_damping.y = 0.5; - rigidbody.data.angular_damping = 0.5; + rigidbody.data.linear_velocity_factor.x = 0.5; + rigidbody.data.linear_velocity_factor.y = 0.5; + rigidbody.data.angular_velocity_factor = 0.5; system.update(); EXPECT_EQ(rigidbody.data.linear_velocity.x, 0.5); EXPECT_EQ(rigidbody.data.linear_velocity.y, 0.5); EXPECT_EQ(rigidbody.data.angular_velocity, 0.5); rigidbody.data.constraints = {1, 1, 0}; - rigidbody.data.angular_damping = 0; + rigidbody.data.angular_velocity_factor = 0; rigidbody.data.max_angular_velocity = 1000; rigidbody.data.angular_velocity = 360; system.update(); diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index a88bf85..e46d5ff 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -26,14 +26,6 @@ using namespace std::chrono_literals; using namespace crepe; using namespace testing; - -/* -List of test cases with component settings/details -1. Minimal test creates gameobject without additonal components -2. Minimal 'Complex' gameobject. Has dynamic body without bounce and no collision handler -3. Minimal 'Complex' gameobject. Same as test 2 but with particle emitter -*/ - class TestScript : public Script { bool oncollision(const CollisionEvent& test) { Log::logf("Box {} script on_collision()", test.info.first_collider.game_object_id); @@ -55,7 +47,7 @@ public: // Minimum amount to let test pass const int min_gameobject_count = 100; // Maximum amount to stop test - const int max_gameobject_count = 200; + const int max_gameobject_count = 150; // Amount of times a test runs to calculate average const int average = 5; // Maximum duration to stop test -- cgit v1.2.3 From ff618da3f97237796042fa3664da59ed147bc1da Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Tue, 3 Dec 2024 19:32:15 +0100 Subject: improved comments --- src/crepe/Collider.h | 18 +++- src/crepe/api/BoxCollider.cpp | 2 +- src/crepe/api/BoxCollider.h | 10 +-- src/crepe/api/Rigidbody.h | 128 +++++++++++++++++++++++---- src/crepe/system/CollisionSystem.cpp | 167 ++++++++++++++++------------------- src/crepe/system/CollisionSystem.h | 32 ++----- src/crepe/system/PhysicsSystem.cpp | 8 +- src/example/game.cpp | 4 +- src/test/CollisionTest.cpp | 56 ++++++------ src/test/PhysicsTest.cpp | 8 +- src/test/Profiling.cpp | 2 +- 11 files changed, 257 insertions(+), 178 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index 15d3a24..f5f53d2 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -10,7 +10,23 @@ public: Collider(game_object_id_t id, const vec2& offset); public: - //! Offset of the collider relative to rigidbody position + /** + * \brief Offset of the collider relative to the rigidbody position. + * + * The `offset` defines the positional shift applied to the collider relative to the position of the rigidbody it is attached to. + * This allows the collider to be placed at a different position than the rigidbody, which can be useful for scenarios + * where the collider's position needs to differ from the rigidbody's center, such as in non-centered colliders. + * + * - The `offset` is typically used when the collider is not meant to be centered exactly on the rigidbody's position. + * - For example, the collider might need to be shifted to account for an object with an asymmetrical shape or for objects + * where the pivot point of the rigidbody is different from the collider's center. + * + * When multiple colliders are added to the same object (e.g., a character with separate body parts or a vehicle with multiple zones), + * the offset is important for properly positioning each collider relative to the rigidbody, allowing accurate collision detection. + * + * - Multiple colliders can be used on the same object, and each can have its own unique offset. + * - Overlap between colliders is allowed and does not impact performance. + */ vec2 offset; }; diff --git a/src/crepe/api/BoxCollider.cpp b/src/crepe/api/BoxCollider.cpp index 1069e90..f94ced7 100644 --- a/src/crepe/api/BoxCollider.cpp +++ b/src/crepe/api/BoxCollider.cpp @@ -4,4 +4,4 @@ using namespace crepe; -BoxCollider::BoxCollider(game_object_id_t game_object_id,const vec2& offset, float width, float height) : Collider(game_object_id,offset), width(width), height(height) {} +BoxCollider::BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions) : Collider(game_object_id,offset), dimensions(dimensions) {} diff --git a/src/crepe/api/BoxCollider.h b/src/crepe/api/BoxCollider.h index c83d54a..1f5f1c1 100644 --- a/src/crepe/api/BoxCollider.h +++ b/src/crepe/api/BoxCollider.h @@ -2,6 +2,7 @@ #include "Vector2.h" #include "../Collider.h" +#include "types.h" namespace crepe { @@ -12,13 +13,10 @@ namespace crepe { */ class BoxCollider : public Collider { public: - BoxCollider(game_object_id_t game_object_id,const vec2& offset, float width, float height); + BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions); - //! Width of box collider - float width; - - //! Height of box collider - float height; + //! Width and height of the box collider + vec2 dimensions; }; } // namespace crepe diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 63b1b51..9cdf3f5 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -36,11 +36,11 @@ public: * the systems will not move the object. */ struct PhysicsConstraints { - //! X constraint + //! Prevent movement along X axis bool x = false; - //! Y constraint + //! Prevent movement along Y axis bool y = false; - //! rotation constraint + //! Prevent rotation bool rotation = false; }; @@ -53,27 +53,112 @@ public: struct Data { //! objects mass float mass = 0.0; - //! gravtiy scale + /** + * \brief Gravity scale factor. + * + * The `gravity_scale` controls how much gravity affects the object. It is a multiplier applied to the default + * gravity force, allowing for fine-grained control over how the object responds to gravity. + * + * - A value of `0.0` means that gravity has **no effect** on the object (i.e., the object is completely immune to gravity). + * - A value of `1.0` means that gravity is applied at its **normal intensity** (the default behavior). + * - A value greater than `1.0` means the object is affected by gravity more strongly than normal. + * - A value less than `1.0` (but greater than `0.0`) reduces the effect of gravity on the object. + * + * This is useful in cases where you need objects to behave differently under gravity, such as lighter objects (like feathers), + * objects that float in water, or heavier objects that fall faster. + */ float gravity_scale = 0; - //! Changes if physics apply + /** + * \brief Defines the type of the physics body, which determines how the physics system interacts with the object. + * + * - **Static**: The object does not move and is not affected by forces. It is used for immovable objects like walls or terrain. Does not have collision detection. + * - **Dynamic**: The object is fully affected by physics forces, including gravity, collisions, and other physical interactions. It can move and be moved by forces. + * - **Kinematic**: The object does not move and is not affected by forces. It is typically controlled by external factors (e.g., animations or user input), and collision detection is handled without affecting its velocity. + * + * The `body_type` defines the behavior of the object in the physics system. + * + * \default BodyType::DYNAMIC + */ BodyType body_type = BodyType::DYNAMIC; - //! linear velocity of object + + /** + * \name Linear (positional) motion + * + * These variables define the linear motion (movement along the position) of an object. + * The linear velocity is applied to the object's position in each update of the PhysicsSystem. + * The motion is affected by the object's linear velocity, its maximum velocity, and a coefficient + * that can scale the velocity over time. + * + * \{ + */ + //! Linear velocity of the object (speed and direction). vec2 linear_velocity; - //! maximum linear velocity of object + //! Maximum linear velocity of the object. This limits the object's speed. vec2 max_linear_velocity = {INFINITY ,INFINITY}; - //! linear damping of object - vec2 linear_velocity_factor; - //! angular velocity of object + //! Linear velocity coefficient. This scales the object's velocity for adjustment or damping. + vec2 linear_velocity_coefficient = {1,1}; + //! \} + + /** + * \name Angular (rotational) motion + * + * These variables define the angular motion (rotation) of an object. + * The angular velocity determines how quickly the object rotates, while the maximum angular velocity + * sets a limit on the rotation speed. The angular velocity coefficient applies damping or scaling + * to the angular velocity, which can be used to simulate friction or other effects that slow down rotation. + * + * \{ + */ + //! Angular velocity of the object, representing the rate of rotation (in radians per second). float angular_velocity = 1; - //! max angular velocity of object + //! Maximum angular velocity of the object. This limits the maximum rate of rotation. float max_angular_velocity = INFINITY; - //! angular damping of object - float angular_velocity_factor = 1; - //! movements constraints of object + //! Angular velocity coefficient. This scales the object's angular velocity, typically used for damping. + float angular_velocity_coefficient = 1; + //! \} + + /** + * \brief Movement constraints for an object. + * + * The `PhysicsConstraints` struct defines the constraints that restrict an object's movement + * in certain directions or prevent rotation. These constraints effect only the physics system + * to prevent the object from moving or rotating in specified ways. + * + * - **X Constraint**: If enabled, the object cannot move along the X-axis. + * - **Y Constraint**: If enabled, the object cannot move along the Y-axis. + * - **Rotation Constraint**: If enabled, the object cannot rotate. + * + * These constraints allow you to restrict movement for specific scenarios (e.g., a platform that shouldn't move + * or a character that should only move horizontally). + */ PhysicsConstraints constraints; - //! bounce factor of material. 0.0 <= means all velocity is lost, 1.0 means it gets the same momentum but the mirrored direction. 0.5 is half of the velocity is saved. - float elastisity = 0.0; - //! offset of all colliders relative to transform position + + /** + * \brief Elasticity factor of the material (bounce factor). + * + * The `elasticity_coefficient` controls how much of the object's velocity is retained after a collision. + * It represents the material's ability to bounce or recover velocity upon impact. The coefficient is a value + * between 0.0 and 1.0, where: + * + * - **0.0** means no velocity is retained after the collision (all velocity is lost, and the object does not bounce). + * - **1.0** means the object retains its full velocity but in the opposite direction (perfect elastic bounce). + * - **0.5** means the object retains half of its velocity, resulting in a bounce with reduced speed. + * + * This factor can be used to simulate different materials, such as rubber (high elasticity) or concrete (low elasticity). + */ + float elastisity_coefficient = 0.0; + + /** + * \brief Offset of all colliders relative to the object's transform position. + * + * The `offset` defines a positional shift applied to all colliders associated with the object, relative to the object's + * transform position. This allows for the colliders to be placed at a different position than the object's actual + * position, without modifying the object's transform itself. + * + * - The `offset` is typically used to adjust the collider's position in cases where all colluders should be moved. + * - For example, if a character has a animation where all colliders should be moved this offset can be used to + * achieve this. + */ vec2 offset; }; @@ -99,6 +184,15 @@ public: * \param force Vector2 that is added to the angular force. */ void add_force_angular(float force); + +protected: + /** + * Ensures there is at most one Rigidbody component per entity. + * \return Always returns 1, indicating this constraint. + */ + virtual int get_instances_max() const { return 1; } + //! ComponentManager instantiates all components + friend class ComponentManager; }; } // namespace crepe diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 380cc3d..2d5ce9d 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -10,6 +10,7 @@ #include "api/EventManager.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" +#include "api/Metadata.h" #include "api/Vector2.h" #include "api/Rigidbody.h" #include "api/Transform.h" @@ -23,18 +24,16 @@ using namespace crepe; void CollisionSystem::update() { - std::vector all_colliders; - ComponentManager & mgr = this->component_manager; game_object_id_t id = 0; - RefVector rigidbodies = mgr.get_components_by_type(); + RefVector rigidbodies = this->component_manager.get_components_by_type(); // Collisions can only happen on object with a rigidbody for(Rigidbody& rigidbody : rigidbodies) { if (!rigidbody.active) continue; id = rigidbody.game_object_id; Transform& transform = this->component_manager.get_components_by_id(id).front().get(); // Check if the boxcollider is active and has the same id as the rigidbody. - RefVector boxcolliders = mgr.get_components_by_type(); + RefVector boxcolliders = this->component_manager.get_components_by_type(); for (BoxCollider& boxcollider : boxcolliders) { if(boxcollider.game_object_id != id) continue; if(!boxcollider.active) continue; @@ -48,7 +47,7 @@ void CollisionSystem::update() { ); } // Check if the circlecollider is active and has the same id as the rigidbody. - RefVector circlecolliders = mgr.get_components_by_type(); + RefVector circlecolliders = this->component_manager.get_components_by_type(); for (CircleCollider& circlecollider : circlecolliders) { if(circlecollider.game_object_id != id) continue; if(!circlecollider.active) continue; @@ -64,59 +63,63 @@ void CollisionSystem::update() { } // Check between all colliders if there is a collision - std::vector> collided = gather_collisions(all_colliders); + std::vector> collided = this->gather_collisions(all_colliders); // For both objects call the collision handler for (auto& collision_pair : collided) { - collision_handler_request(collision_pair.first,collision_pair.second); - collision_handler_request(collision_pair.second,collision_pair.first); + this->collision_handler_request(collision_pair.first,collision_pair.second); + this->collision_handler_request(collision_pair.second,collision_pair.first); } } -void CollisionSystem::collision_handler_request(CollisionInternal& data1,CollisionInternal& data2){ +void CollisionSystem::collision_handler_request(CollisionInternal& this_data,CollisionInternal& other_data){ - CollisionInternalType type = get_collider_type(data1.collider,data2.collider); - std::pair resolution_data = collision_handler(data1,data2,type); + CollisionInternalType type = this->get_collider_type(this_data.collider,other_data.collider); + std::pair resolution_data = this->collision_handler(this_data,other_data,type); - OptionalRef collider1; - OptionalRef collider2; + OptionalRef this_metadata = this->component_manager.get_components_by_id(this_data.id).front().get(); + OptionalRef other_metadata = this->component_manager.get_components_by_id(other_data.id).front().get(); + OptionalRef this_collider; + OptionalRef other_collider; switch (type) { case CollisionInternalType::BOX_BOX:{ - collider1 = std::get>(data1.collider); - collider2 = std::get>(data2.collider); + this_collider = std::get>(this_data.collider); + other_collider = std::get>(other_data.collider); break; } case CollisionInternalType::BOX_CIRCLE:{ - collider1 = std::get>(data1.collider); - collider2 = std::get>(data2.collider); + this_collider = std::get>(this_data.collider); + other_collider = std::get>(other_data.collider); break; } case CollisionInternalType::CIRCLE_BOX:{ - collider1 = std::get>(data1.collider); - collider2 = std::get>(data2.collider); + this_collider = std::get>(this_data.collider); + other_collider = std::get>(other_data.collider); break; } case CollisionInternalType::CIRCLE_CIRCLE:{ - collider1 = std::get>(data1.collider); - collider2 = std::get>(data2.collider); + this_collider = std::get>(this_data.collider); + other_collider = std::get>(other_data.collider); break; } } - + // collision info crepe::CollisionSystem::CollisionInfo collision_info{ - .first_collider = collider1, - .first_transform = data1.transform, - .first_rigidbody = data1.rigidbody, - .second_collider = collider2, - .second_transform = data2.transform, - .second_rigidbody = data2.rigidbody, + .this_collider = this_collider, + .this_transform = this_data.transform, + .this_rigidbody = this_data.rigidbody, + .this_metadata = this_metadata, + .other_collider = other_collider, + .other_transform = other_data.transform, + .other_rigidbody = other_data.rigidbody, + .other_metadata = other_metadata, .resolution = resolution_data.first, .resolution_direction = resolution_data.second, }; // Determine if static needs to be called - determine_collision_handler(collision_info); + this->determine_collision_handler(collision_info); } @@ -126,33 +129,33 @@ std::pair CollisionSystem::collision_handler(Co case CollisionInternalType::BOX_BOX: { const BoxCollider & collider1 = std::get>(data1.collider); const BoxCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_box_box_resolution(collider1,collider2,collider_pos1,collider_pos2); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_box_box_resolution(collider1,collider2,collider_pos1,collider_pos2); break; } case CollisionInternalType::BOX_CIRCLE: { const BoxCollider & collider1 = std::get>(data1.collider); const CircleCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_circle_box_resolution(collider2,collider1,collider_pos2,collider_pos1); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_circle_box_resolution(collider2,collider1,collider_pos2,collider_pos1); break; } case CollisionInternalType::CIRCLE_CIRCLE: { const CircleCollider & collider1 = std::get>(data1.collider); const CircleCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_circle_circle_resolution(collider1,collider2,collider_pos1,collider_pos2); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_circle_circle_resolution(collider1,collider2,collider_pos1,collider_pos2); break; } case CollisionInternalType::CIRCLE_BOX: { const CircleCollider & collider1 = std::get>(data1.collider); const BoxCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_circle_box_resolution(collider1,collider2,collider_pos1,collider_pos2); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_circle_box_resolution(collider1,collider2,collider_pos1,collider_pos2); break; } } @@ -179,10 +182,10 @@ vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,co vec2 delta = final_position2 - final_position1; // Compute half-dimensions of the boxes - float half_width1 = box_collider1.width / 2.0; - float half_height1 = box_collider1.height / 2.0; - float half_width2 = box_collider2.width / 2.0; - float half_height2 = box_collider2.height / 2.0; + float half_width1 = box_collider1.dimensions.x / 2.0; + float half_height1 = box_collider1.dimensions.y / 2.0; + float half_width2 = box_collider2.dimensions.x / 2.0; + float half_height2 = box_collider2.dimensions.y / 2.0; // Calculate overlaps along X and Y axes float overlap_x = (half_width1 + half_width2) - std::abs(delta.x); @@ -234,8 +237,8 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_col vec2 delta = circle_position - box_position; // Compute half-dimensions of the box - float half_width = box_collider.width / 2.0f; - float half_height = box_collider.height / 2.0f; + float half_width = box_collider.dimensions.x / 2.0f; + float half_height = box_collider.dimensions.y / 2.0f; // Clamp circle center to the nearest point on the box vec2 closest_point; @@ -261,37 +264,37 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_col void CollisionSystem::determine_collision_handler(CollisionInfo& info){ // Check rigidbody type for static - if(info.first_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return; + if(info.this_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return; // If second body is static perform the static collision handler in this system - if(info.second_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){ + if(info.other_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){ static_collision_handler(info); }; // Call collision event for user CollisionEvent data(info); - EventManager::get_instance().trigger_event(data, info.first_collider.game_object_id); + EventManager::get_instance().trigger_event(data, info.this_collider.game_object_id); } void CollisionSystem::static_collision_handler(CollisionInfo& info){ // Move object back using calculate move back value - info.first_transform.position += info.resolution; + info.this_transform.position += info.resolution; // If bounce is enabled mirror velocity - if(info.first_rigidbody.data.elastisity > 0) { + if(info.this_rigidbody.data.elastisity_coefficient > 0) { if(info.resolution_direction == Direction::BOTH) { - info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity; - info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity; + info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient; + info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient; } else if(info.resolution_direction == Direction::Y_DIRECTION) { - info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity; + info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient; } else if(info.resolution_direction == Direction::X_DIRECTION){ - info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity; + info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient; } } // Stop movement if bounce is disabled else { - info.first_rigidbody.data.linear_velocity = {0,0}; + info.this_rigidbody.data.linear_velocity = {0,0}; } } @@ -332,24 +335,6 @@ std::vector, std::reference_wrapper>> -CollisionSystem::get_active_transform_and_rigidbody(game_object_id_t game_object_id) const{ - RefVector transforms = this->component_manager.get_components_by_id(game_object_id); - if (transforms.empty()) return std::nullopt; - - Transform& transform = transforms.front().get(); - if (!transform.active) return std::nullopt; - - RefVector rigidbodies = this->component_manager.get_components_by_id(game_object_id); - if (rigidbodies.empty()) return std::nullopt; - - Rigidbody& rigidbody = rigidbodies.front().get(); - if (!rigidbody.active) return std::nullopt; - - // Return the active components - return std::make_pair(std::ref(transform), std::ref(rigidbody)); -} - CollisionSystem::CollisionInternalType CollisionSystem::get_collider_type(const collider_variant& collider1,const collider_variant& collider2) const{ if(std::holds_alternative>(collider1)){ if(std::holds_alternative>(collider2)) @@ -376,22 +361,22 @@ bool CollisionSystem::get_collision(const CollisionInternal& first_info,const Co case CollisionInternalType::BOX_BOX: { const BoxCollider & box_collider1 = std::get>(first_info.collider); const BoxCollider & box_collider2 = std::get>(second_info.collider); - return get_box_box_collision(box_collider1,box_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_box_box_collision(box_collider1,box_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } case CollisionInternalType::BOX_CIRCLE: { const BoxCollider & box_collider = std::get>(first_info.collider); const CircleCollider & circle_collider = std::get>(second_info.collider); - return get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } case CollisionInternalType::CIRCLE_CIRCLE: { const CircleCollider & circle_collider1 = std::get>(first_info.collider); const CircleCollider & circle_collider2 = std::get>(second_info.collider); - return get_circle_circle_collision(circle_collider1,circle_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_circle_circle_collision(circle_collider1,circle_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } case CollisionInternalType::CIRCLE_BOX: { const CircleCollider & circle_collider = std::get>(first_info.collider); const BoxCollider & box_collider = std::get>(second_info.collider); - return get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } } return false; @@ -401,14 +386,14 @@ bool CollisionSystem::get_collision(const CollisionInternal& first_info,const Co bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = get_current_position(box1.offset,transform1,rigidbody1); - vec2 final_position2 = get_current_position(box2.offset,transform2,rigidbody2); + vec2 final_position1 = this->get_current_position(box1.offset,transform1,rigidbody1); + vec2 final_position2 = this->get_current_position(box2.offset,transform2,rigidbody2); // Calculate half-extents (half width and half height) - float half_width1 = box1.width / 2.0; - float half_height1 = box1.height / 2.0; - float half_width2 = box2.width / 2.0; - float half_height2 = box2.height / 2.0; + float half_width1 = box1.dimensions.x / 2.0; + float half_height1 = box1.dimensions.y / 2.0; + float half_width2 = box2.dimensions.x / 2.0; + float half_height2 = box2.dimensions.y / 2.0; // Check if the boxes overlap along the X and Y axes return (final_position1.x + half_width1 > final_position2.x - half_width2 && @@ -419,12 +404,12 @@ bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCo bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = get_current_position(box1.offset, transform1, rigidbody1); - vec2 final_position2 = get_current_position(circle2.offset, transform2, rigidbody2); + vec2 final_position1 = this->get_current_position(box1.offset, transform1, rigidbody1); + vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2); // Calculate box half-extents - float half_width = box1.width / 2.0; - float half_height = box1.height / 2.0; + float half_width = box1.dimensions.x / 2.0; + float half_height = box1.dimensions.y / 2.0; // Find the closest point on the box to the circle's center float closest_x = std::max(final_position1.x - half_width, std::min(final_position2.x, final_position1.x + half_width)); @@ -441,8 +426,8 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const Ci bool CollisionSystem::get_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = get_current_position(circle1.offset,transform1,rigidbody1); - vec2 final_position2 = get_current_position(circle2.offset,transform2,rigidbody2); + vec2 final_position1 = this->get_current_position(circle1.offset,transform1,rigidbody1); + vec2 final_position2 = this->get_current_position(circle2.offset,transform2,rigidbody2); float distance_x = final_position1.x - final_position2.x; float distance_y = final_position1.y - final_position2.y; diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 7fb8b45..85ae5ad 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -8,6 +8,7 @@ #include "api/Transform.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" +#include "api/Metadata.h" #include "api/Vector2.h" #include "Collider.h" @@ -68,12 +69,14 @@ public: * Includes information about the colliding objects and the resolution data for handling the collision. */ struct CollisionInfo{ - Collider& first_collider; - Transform& first_transform; - Rigidbody& first_rigidbody; - Collider& second_collider; - Transform& second_transform; - Rigidbody& second_rigidbody; + Collider& this_collider; + Transform& this_transform; + Rigidbody& this_rigidbody; + Metadata& this_metadata; + Collider& other_collider; + Transform& other_transform; + Rigidbody& other_rigidbody; + Metadata& other_metadata; //! The resolution vector for the collision. vec2 resolution; //! The direction of movement for resolving the collision. @@ -213,23 +216,6 @@ private: */ bool get_collision(const CollisionInternal& first_info,const CollisionInternal& second_info, CollisionInternalType type) const; - /** - * \brief Retrieves the active Transform and Rigidbody components for a given game object. - * - * This function looks up the Transform and Rigidbody components associated with the specified - * game object ID. It checks if both components are present and active. If both are found - * to be active, they are returned wrapped in reference wrappers; otherwise, an empty - * optional is returned. - * - * \param game_object_id The ID of the game object for which to retrieve the components. - * - * \return A std::optional containing a pair of reference wrappers to the active Transform - * and Rigidbody components, or std::nullopt if either component is not found - * or not active. - */ - std::optional, std::reference_wrapper>> get_active_transform_and_rigidbody(game_object_id_t game_object_id) const; - - /** * \brief Detects collisions between two BoxColliders. * diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index 8f21727..f3833cb 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -31,11 +31,11 @@ void PhysicsSystem::update() { * gravity); } // Add damping - if (rigidbody.data.angular_velocity_factor != 1 && rigidbody.data.angular_velocity_factor > 0) { - rigidbody.data.angular_velocity *= rigidbody.data.angular_velocity_factor; + if (rigidbody.data.angular_velocity_coefficient != 1 && rigidbody.data.angular_velocity_coefficient > 0) { + rigidbody.data.angular_velocity *= rigidbody.data.angular_velocity_coefficient; } - if (rigidbody.data.linear_velocity_factor != vec2{1, 1} && rigidbody.data.linear_velocity_factor.x > 0 && rigidbody.data.linear_velocity_factor.y > 0) { - rigidbody.data.linear_velocity *= rigidbody.data.linear_velocity_factor; + if (rigidbody.data.linear_velocity_coefficient != vec2{1, 1} && rigidbody.data.linear_velocity_coefficient.x > 0 && rigidbody.data.linear_velocity_coefficient.y > 0) { + rigidbody.data.linear_velocity *= rigidbody.data.linear_velocity_coefficient; } // Max velocity check diff --git a/src/example/game.cpp b/src/example/game.cpp index c439f5d..4e16d4a 100644 --- a/src/example/game.cpp +++ b/src/example/game.cpp @@ -18,7 +18,7 @@ using namespace std; class MyScript : public Script { bool oncollision(const CollisionEvent& test) { - Log::logf("Box {} script on_collision()", test.info.first_collider.game_object_id); + Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id); return true; } void init() { @@ -65,7 +65,7 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {1,1}, .constraints = {0, 0, 0}, - .elastisity = 1, + .elastisity_coefficient = 1, .offset = {0,0}, }); game_object1.add_component(vec2{0, 0}, 20, 20); diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index 92ff7ba..fec42f3 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -68,10 +68,10 @@ public: .offset = {0,0}, }); // Create a box with an inner size of 10x10 units - world.add_component(vec2{0, -100}, 100, 100); // Top - world.add_component(vec2{0, 100}, 100, 100); // Bottom - world.add_component(vec2{-100, 0}, 100, 100); // Left - world.add_component(vec2{100, 0}, 100, 100); // right + world.add_component(vec2{0, -100}, vec2{100, 100}); // Top + world.add_component(vec2{0, 100}, vec2{100, 100}); // Bottom + world.add_component(vec2{-100, 0}, vec2{100, 100}); // Left + world.add_component(vec2{100, 0}, vec2{100, 100}); // right game_object1.add_component(Rigidbody::Data{ .mass = 1, @@ -79,10 +79,10 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {0,0}, .constraints = {0, 0, 0}, - .elastisity = 1, + .elastisity_coefficient = 1, .offset = {0,0}, }); - game_object1.add_component(vec2{0, 0}, 10, 10); + game_object1.add_component(vec2{0, 0}, vec2{10, 10}); BehaviorScript & script_object1 = game_object1.add_component().set_script(1); script_object1_ref = static_cast(script_object1.script.get()); ASSERT_NE(script_object1_ref, nullptr); @@ -93,10 +93,10 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {0,0}, .constraints = {0, 0, 0}, - .elastisity = 1, + .elastisity_coefficient = 1, .offset = {0,0}, }); - game_object2.add_component(vec2{0, 0}, 10, 10); + game_object2.add_component(vec2{0, 0}, vec2{10, 10}); BehaviorScript & script_object2 = game_object2.add_component().set_script(2); script_object2_ref = static_cast(script_object2.script.get()); ASSERT_NE(script_object2_ref, nullptr); @@ -110,11 +110,11 @@ TEST_F(CollisionTest, collision_example) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); }; EXPECT_FALSE(collision_happend); collision_sys.update(); @@ -125,14 +125,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); @@ -148,14 +148,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, 0); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 0); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); @@ -171,14 +171,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 0); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 0); EXPECT_EQ(ev.info.resolution.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); @@ -194,14 +194,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); @@ -221,14 +221,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); @@ -248,14 +248,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); @@ -276,7 +276,7 @@ TEST_F(CollisionTest, collision_box_box_static_both) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); @@ -298,7 +298,7 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); @@ -322,7 +322,7 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); @@ -348,8 +348,8 @@ TEST_F(CollisionTest, collision_box_box_static_multiple) {//todo check visually float resolution = 0; script_object1_ref->test_fn = [&](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); - EXPECT_EQ(ev.info.first_collider.offset.x , offset_value); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.offset.x , offset_value); EXPECT_EQ(ev.info.resolution.x , resolution); }; script_object2_ref->test_fn = [&](const CollisionEvent & ev) { @@ -365,7 +365,7 @@ TEST_F(CollisionTest, collision_box_box_static_multiple) {//todo check visually rg2.data.body_type = crepe::Rigidbody::BodyType::STATIC; BoxCollider & bxc = this->mgr.get_components_by_id(1).front().get(); bxc.offset = {5,0}; - this->game_object1.add_component(vec2{-5, 0}, 10, 10); + this->game_object1.add_component(vec2{-5, 0}, vec2{10, 10}); offset_value = 5; resolution = 10; collision_sys.update(); diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 5dd448f..ad7cb03 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -103,16 +103,16 @@ TEST_F(PhysicsTest, movement) { EXPECT_EQ(transform.position.y, 1); EXPECT_EQ(transform.rotation, 1); - rigidbody.data.linear_velocity_factor.x = 0.5; - rigidbody.data.linear_velocity_factor.y = 0.5; - rigidbody.data.angular_velocity_factor = 0.5; + rigidbody.data.linear_velocity_coefficient.x = 0.5; + rigidbody.data.linear_velocity_coefficient.y = 0.5; + rigidbody.data.angular_velocity_coefficient = 0.5; system.update(); EXPECT_EQ(rigidbody.data.linear_velocity.x, 0.5); EXPECT_EQ(rigidbody.data.linear_velocity.y, 0.5); EXPECT_EQ(rigidbody.data.angular_velocity, 0.5); rigidbody.data.constraints = {1, 1, 0}; - rigidbody.data.angular_velocity_factor = 0; + rigidbody.data.angular_velocity_coefficient = 0; rigidbody.data.max_angular_velocity = 1000; rigidbody.data.angular_velocity = 360; system.update(); diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index e46d5ff..fa0f5f3 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -28,7 +28,7 @@ using namespace testing; class TestScript : public Script { bool oncollision(const CollisionEvent& test) { - Log::logf("Box {} script on_collision()", test.info.first_collider.game_object_id); + Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id); return true; } void init() { -- cgit v1.2.3 From d76ab0bf77d0a61712dc25bbe1760995be4c4782 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Wed, 4 Dec 2024 20:11:02 +0100 Subject: make format --- src/crepe/Collider.cpp | 2 +- src/crepe/Collider.h | 2 +- src/crepe/api/BoxCollider.cpp | 7 +- src/crepe/api/BoxCollider.h | 6 +- src/crepe/api/CircleCollider.cpp | 6 +- src/crepe/api/CircleCollider.h | 3 +- src/crepe/api/Event.h | 4 +- src/crepe/api/LoopManager.cpp | 3 +- src/crepe/api/Rigidbody.cpp | 4 +- src/crepe/api/Rigidbody.h | 4 +- src/crepe/system/CollisionSystem.cpp | 514 ++++++++++++++++++++--------------- src/crepe/system/CollisionSystem.h | 121 +++++---- src/crepe/system/PhysicsSystem.cpp | 9 +- src/example/game.cpp | 97 ++++--- src/test/CollisionTest.cpp | 122 +++++---- src/test/Profiling.cpp | 121 +++++---- 16 files changed, 574 insertions(+), 451 deletions(-) (limited to 'src/test/Profiling.cpp') diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp index 9d94152..77e11c8 100644 --- a/src/crepe/Collider.cpp +++ b/src/crepe/Collider.cpp @@ -2,4 +2,4 @@ using namespace crepe; -Collider::Collider(game_object_id_t id, const vec2& offset) : Component(id), offset(offset) {} +Collider::Collider(game_object_id_t id, const vec2 & offset) : Component(id), offset(offset) {} diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index b3a09fb..a08a68e 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -7,7 +7,7 @@ namespace crepe { class Collider : public Component { public: - Collider(game_object_id_t id, const vec2& offset); + Collider(game_object_id_t id, const vec2 & offset); public: /** diff --git a/src/crepe/api/BoxCollider.cpp b/src/crepe/api/BoxCollider.cpp index f94ced7..c097a24 100644 --- a/src/crepe/api/BoxCollider.cpp +++ b/src/crepe/api/BoxCollider.cpp @@ -1,7 +1,10 @@ #include "BoxCollider.h" -#include "../Collider.h" +#include "../Collider.h" using namespace crepe; -BoxCollider::BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions) : Collider(game_object_id,offset), dimensions(dimensions) {} +BoxCollider::BoxCollider(game_object_id_t game_object_id, const vec2 & offset, + const vec2 & dimensions) + : Collider(game_object_id, offset), + dimensions(dimensions) {} diff --git a/src/crepe/api/BoxCollider.h b/src/crepe/api/BoxCollider.h index 1f5f1c1..89e43d8 100644 --- a/src/crepe/api/BoxCollider.h +++ b/src/crepe/api/BoxCollider.h @@ -1,7 +1,7 @@ #pragma once -#include "Vector2.h" #include "../Collider.h" +#include "Vector2.h" #include "types.h" namespace crepe { @@ -13,9 +13,9 @@ namespace crepe { */ class BoxCollider : public Collider { public: - BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions); + BoxCollider(game_object_id_t game_object_id, const vec2 & offset, const vec2 & dimensions); - //! Width and height of the box collider + //! Width and height of the box collider vec2 dimensions; }; diff --git a/src/crepe/api/CircleCollider.cpp b/src/crepe/api/CircleCollider.cpp index 473734e..a4271e9 100644 --- a/src/crepe/api/CircleCollider.cpp +++ b/src/crepe/api/CircleCollider.cpp @@ -2,5 +2,7 @@ using namespace crepe; - -CircleCollider::CircleCollider(game_object_id_t game_object_id,const vec2& offset, float radius) : Collider(game_object_id,offset), radius(radius) {} +CircleCollider::CircleCollider(game_object_id_t game_object_id, const vec2 & offset, + float radius) + : Collider(game_object_id, offset), + radius(radius) {} diff --git a/src/crepe/api/CircleCollider.h b/src/crepe/api/CircleCollider.h index bbcc330..ebd1cb2 100644 --- a/src/crepe/api/CircleCollider.h +++ b/src/crepe/api/CircleCollider.h @@ -13,8 +13,7 @@ namespace crepe { */ class CircleCollider : public Collider { public: - - CircleCollider(game_object_id_t game_object_id,const vec2& offset, float radius); + CircleCollider(game_object_id_t game_object_id, const vec2 & offset, float radius); //! Radius of the circle collider. float radius; diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 259acba..152bc2c 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -98,8 +98,8 @@ public: class CollisionEvent : public Event { public: crepe::CollisionSystem::CollisionInfo info; - CollisionEvent(const crepe::CollisionSystem::CollisionInfo& collisionInfo) - : info(collisionInfo) {} + CollisionEvent(const crepe::CollisionSystem::CollisionInfo & collisionInfo) + : info(collisionInfo) {} }; /** diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index feb1338..d4819ea 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,13 +1,12 @@ #include "../facade/SDLContext.h" +#include "../system/PhysicsSystem.h" #include "../system/AnimatorSystem.h" #include "../system/CollisionSystem.h" #include "../system/ParticleSystem.h" #include "../system/PhysicsSystem.h" #include "../system/RenderSystem.h" #include "../system/ScriptSystem.h" -#include "..//system/PhysicsSystem.h" -#include "../system/CollisionSystem.h" #include "LoopManager.h" #include "LoopTimer.h" diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp index c4b1d6f..8213afb 100644 --- a/src/crepe/api/Rigidbody.cpp +++ b/src/crepe/api/Rigidbody.cpp @@ -10,6 +10,4 @@ void crepe::Rigidbody::add_force_linear(const vec2 & force) { this->data.linear_velocity += force; } -void crepe::Rigidbody::add_force_angular(float force) { - this->data.angular_velocity += force; -} +void crepe::Rigidbody::add_force_angular(float force) { this->data.angular_velocity += force; } diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 431e000..756cc28 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -78,9 +78,9 @@ public: //! Linear velocity of the object (speed and direction). vec2 linear_velocity; //! Maximum linear velocity of the object. This limits the object's speed. - vec2 max_linear_velocity = {INFINITY ,INFINITY}; + vec2 max_linear_velocity = {INFINITY, INFINITY}; //! Linear velocity coefficient. This scales the object's velocity for adjustment or damping. - vec2 linear_velocity_coefficient = {1,1}; + vec2 linear_velocity_coefficient = {1, 1}; //! \} /** diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 2d5ce9d..34cd125 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -1,23 +1,23 @@ -#include #include +#include #include #include +#include #include #include -#include -#include "api/Event.h" -#include "api/EventManager.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" +#include "api/Event.h" +#include "api/EventManager.h" #include "api/Metadata.h" -#include "api/Vector2.h" #include "api/Rigidbody.h" #include "api/Transform.h" +#include "api/Vector2.h" -#include "ComponentManager.h" -#include "CollisionSystem.h" #include "Collider.h" +#include "CollisionSystem.h" +#include "ComponentManager.h" #include "types.h" #include "util/OptionalRef.h" @@ -26,158 +26,191 @@ using namespace crepe; void CollisionSystem::update() { std::vector all_colliders; game_object_id_t id = 0; - RefVector rigidbodies = this->component_manager.get_components_by_type(); + RefVector rigidbodies + = this->component_manager.get_components_by_type(); // Collisions can only happen on object with a rigidbody - for(Rigidbody& rigidbody : rigidbodies) { + for (Rigidbody & rigidbody : rigidbodies) { if (!rigidbody.active) continue; id = rigidbody.game_object_id; - Transform& transform = this->component_manager.get_components_by_id(id).front().get(); + Transform & transform + = this->component_manager.get_components_by_id(id).front().get(); // Check if the boxcollider is active and has the same id as the rigidbody. - RefVector boxcolliders = this->component_manager.get_components_by_type(); - for (BoxCollider& boxcollider : boxcolliders) { - if(boxcollider.game_object_id != id) continue; - if(!boxcollider.active) continue; - all_colliders.push_back( - { - .id = id, - .collider = collider_variant{boxcollider}, - .transform = transform, - .rigidbody = rigidbody - } - ); + RefVector boxcolliders + = this->component_manager.get_components_by_type(); + for (BoxCollider & boxcollider : boxcolliders) { + if (boxcollider.game_object_id != id) continue; + if (!boxcollider.active) continue; + all_colliders.push_back({.id = id, + .collider = collider_variant{boxcollider}, + .transform = transform, + .rigidbody = rigidbody}); } // Check if the circlecollider is active and has the same id as the rigidbody. - RefVector circlecolliders = this->component_manager.get_components_by_type(); - for (CircleCollider& circlecollider : circlecolliders) { - if(circlecollider.game_object_id != id) continue; - if(!circlecollider.active) continue; - all_colliders.push_back( - { - .id = id, - .collider = collider_variant{circlecollider}, - .transform = transform, - .rigidbody = rigidbody - } - ); + RefVector circlecolliders + = this->component_manager.get_components_by_type(); + for (CircleCollider & circlecollider : circlecolliders) { + if (circlecollider.game_object_id != id) continue; + if (!circlecollider.active) continue; + all_colliders.push_back({.id = id, + .collider = collider_variant{circlecollider}, + .transform = transform, + .rigidbody = rigidbody}); } } // Check between all colliders if there is a collision - std::vector> collided = this->gather_collisions(all_colliders); + std::vector> collided + = this->gather_collisions(all_colliders); - // For both objects call the collision handler - for (auto& collision_pair : collided) { - this->collision_handler_request(collision_pair.first,collision_pair.second); - this->collision_handler_request(collision_pair.second,collision_pair.first); + // For both objects call the collision handler + for (auto & collision_pair : collided) { + this->collision_handler_request(collision_pair.first, collision_pair.second); + this->collision_handler_request(collision_pair.second, collision_pair.first); } } -void CollisionSystem::collision_handler_request(CollisionInternal& this_data,CollisionInternal& other_data){ +void CollisionSystem::collision_handler_request(CollisionInternal & this_data, + CollisionInternal & other_data) { - CollisionInternalType type = this->get_collider_type(this_data.collider,other_data.collider); - std::pair resolution_data = this->collision_handler(this_data,other_data,type); + CollisionInternalType type + = this->get_collider_type(this_data.collider, other_data.collider); + std::pair resolution_data + = this->collision_handler(this_data, other_data, type); - OptionalRef this_metadata = this->component_manager.get_components_by_id(this_data.id).front().get(); - OptionalRef other_metadata = this->component_manager.get_components_by_id(other_data.id).front().get(); + OptionalRef this_metadata + = this->component_manager.get_components_by_id(this_data.id).front().get(); + OptionalRef other_metadata + = this->component_manager.get_components_by_id(other_data.id).front().get(); OptionalRef this_collider; OptionalRef other_collider; switch (type) { - case CollisionInternalType::BOX_BOX:{ + case CollisionInternalType::BOX_BOX: { this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + other_collider + = std::get>(other_data.collider); break; } - case CollisionInternalType::BOX_CIRCLE:{ + case CollisionInternalType::BOX_CIRCLE: { this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + other_collider + = std::get>(other_data.collider); break; } - case CollisionInternalType::CIRCLE_BOX:{ - this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + case CollisionInternalType::CIRCLE_BOX: { + this_collider + = std::get>(this_data.collider); + other_collider + = std::get>(other_data.collider); break; } - case CollisionInternalType::CIRCLE_CIRCLE:{ - this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + case CollisionInternalType::CIRCLE_CIRCLE: { + this_collider + = std::get>(this_data.collider); + other_collider + = std::get>(other_data.collider); break; } } // collision info crepe::CollisionSystem::CollisionInfo collision_info{ - .this_collider = this_collider, - .this_transform = this_data.transform, - .this_rigidbody = this_data.rigidbody, - .this_metadata = this_metadata, - .other_collider = other_collider, - .other_transform = other_data.transform, - .other_rigidbody = other_data.rigidbody, - .other_metadata = other_metadata, - .resolution = resolution_data.first, - .resolution_direction = resolution_data.second, - }; + .this_collider = this_collider, + .this_transform = this_data.transform, + .this_rigidbody = this_data.rigidbody, + .this_metadata = this_metadata, + .other_collider = other_collider, + .other_transform = other_data.transform, + .other_rigidbody = other_data.rigidbody, + .other_metadata = other_metadata, + .resolution = resolution_data.first, + .resolution_direction = resolution_data.second, + }; // Determine if static needs to be called - this->determine_collision_handler(collision_info); + this->determine_collision_handler(collision_info); } - -std::pair CollisionSystem::collision_handler(CollisionInternal& data1,CollisionInternal& data2,CollisionInternalType type) { +std::pair +CollisionSystem::collision_handler(CollisionInternal & data1, CollisionInternal & data2, + CollisionInternalType type) { vec2 resolution; switch (type) { - case CollisionInternalType::BOX_BOX: { - const BoxCollider & collider1 = std::get>(data1.collider); - const BoxCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = this->get_box_box_resolution(collider1,collider2,collider_pos1,collider_pos2); + case CollisionInternalType::BOX_BOX: { + const BoxCollider & collider1 + = std::get>(data1.collider); + const BoxCollider & collider2 + = std::get>(data2.collider); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, + data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, + data2.rigidbody); + resolution = this->get_box_box_resolution(collider1, collider2, collider_pos1, + collider_pos2); break; } case CollisionInternalType::BOX_CIRCLE: { - const BoxCollider & collider1 = std::get>(data1.collider); - const CircleCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = this->get_circle_box_resolution(collider2,collider1,collider_pos2,collider_pos1); + const BoxCollider & collider1 + = std::get>(data1.collider); + const CircleCollider & collider2 + = std::get>(data2.collider); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, + data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, + data2.rigidbody); + resolution = this->get_circle_box_resolution(collider2, collider1, collider_pos2, + collider_pos1); break; } - case CollisionInternalType::CIRCLE_CIRCLE: { - const CircleCollider & collider1 = std::get>(data1.collider); - const CircleCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = this->get_circle_circle_resolution(collider1,collider2,collider_pos1,collider_pos2); + case CollisionInternalType::CIRCLE_CIRCLE: { + const CircleCollider & collider1 + = std::get>(data1.collider); + const CircleCollider & collider2 + = std::get>(data2.collider); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, + data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, + data2.rigidbody); + resolution = this->get_circle_circle_resolution(collider1, collider2, + collider_pos1, collider_pos2); break; } - case CollisionInternalType::CIRCLE_BOX: { - const CircleCollider & collider1 = std::get>(data1.collider); - const BoxCollider & collider2 = std::get>(data2.collider); - vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = this->get_circle_box_resolution(collider1,collider2,collider_pos1,collider_pos2); + case CollisionInternalType::CIRCLE_BOX: { + const CircleCollider & collider1 + = std::get>(data1.collider); + const BoxCollider & collider2 + = std::get>(data2.collider); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, + data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, + data2.rigidbody); + resolution = this->get_circle_box_resolution(collider1, collider2, collider_pos1, + collider_pos2); break; } } Direction resolution_direction = Direction::NONE; - if(resolution.x != 0 && resolution.y > 0) { + if (resolution.x != 0 && resolution.y > 0) { resolution_direction = Direction::BOTH; } else if (resolution.x != 0) { resolution_direction = Direction::X_DIRECTION; - if(data1.rigidbody.data.linear_velocity.y != 0) - resolution.y = data1.rigidbody.data.linear_velocity.y * (resolution.x/data1.rigidbody.data.linear_velocity.x); + if (data1.rigidbody.data.linear_velocity.y != 0) + resolution.y = data1.rigidbody.data.linear_velocity.y + * (resolution.x / data1.rigidbody.data.linear_velocity.x); } else if (resolution.y != 0) { resolution_direction = Direction::Y_DIRECTION; - if(data1.rigidbody.data.linear_velocity.x != 0) - resolution.x = data1.rigidbody.data.linear_velocity.x * (resolution.y/data1.rigidbody.data.linear_velocity.y); + if (data1.rigidbody.data.linear_velocity.x != 0) + resolution.x = data1.rigidbody.data.linear_velocity.x + * (resolution.y / data1.rigidbody.data.linear_velocity.y); } - return std::make_pair(resolution,resolution_direction); + return std::make_pair(resolution, resolution_direction); } -vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,const vec2& final_position1,const vec2& final_position2) const -{ +vec2 CollisionSystem::get_box_box_resolution(const BoxCollider & box_collider1, + const BoxCollider & box_collider2, + const vec2 & final_position1, + const vec2 & final_position2) const { vec2 resolution; // Default resolution vector vec2 delta = final_position2 - final_position1; @@ -210,97 +243,107 @@ vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,co return resolution; } -vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, const vec2& final_position1, const vec2& final_position2) const -{ - vec2 delta = final_position2 - final_position1; +vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider & circle_collider1, + const CircleCollider & circle_collider2, + const vec2 & final_position1, + const vec2 & final_position2) const { + vec2 delta = final_position2 - final_position1; - // Compute the distance between the two circle centers - float distance = std::sqrt(delta.x * delta.x + delta.y * delta.y); + // Compute the distance between the two circle centers + float distance = std::sqrt(delta.x * delta.x + delta.y * delta.y); - // Compute the combined radii of the two circles - float combined_radius = circle_collider1.radius + circle_collider2.radius; + // Compute the combined radii of the two circles + float combined_radius = circle_collider1.radius + circle_collider2.radius; - // Compute the penetration depth - float penetration_depth = combined_radius - distance; + // Compute the penetration depth + float penetration_depth = combined_radius - distance; - // Normalize the delta vector to get the collision direction - vec2 collision_normal = delta / distance; + // Normalize the delta vector to get the collision direction + vec2 collision_normal = delta / distance; - // Compute the resolution vector - vec2 resolution = collision_normal * penetration_depth; + // Compute the resolution vector + vec2 resolution = collision_normal * penetration_depth; - return resolution; + return resolution; } -vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, const vec2& circle_position, const vec2& box_position) const -{ - vec2 delta = circle_position - box_position; +vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider & circle_collider, + const BoxCollider & box_collider, + const vec2 & circle_position, + const vec2 & box_position) const { + vec2 delta = circle_position - box_position; - // Compute half-dimensions of the box - float half_width = box_collider.dimensions.x / 2.0f; - float half_height = box_collider.dimensions.y / 2.0f; + // Compute half-dimensions of the box + float half_width = box_collider.dimensions.x / 2.0f; + float half_height = box_collider.dimensions.y / 2.0f; - // Clamp circle center to the nearest point on the box - vec2 closest_point; - closest_point.x = std::clamp(delta.x, -half_width, half_width); - closest_point.y = std::clamp(delta.y, -half_height, half_height); + // Clamp circle center to the nearest point on the box + vec2 closest_point; + closest_point.x = std::clamp(delta.x, -half_width, half_width); + closest_point.y = std::clamp(delta.y, -half_height, half_height); - // Find the vector from the circle center to the closest point - vec2 closest_delta = delta - closest_point; + // Find the vector from the circle center to the closest point + vec2 closest_delta = delta - closest_point; - // Normalize the delta to get the collision direction - float distance = std::sqrt(closest_delta.x * closest_delta.x + closest_delta.y * closest_delta.y); - vec2 collision_normal = closest_delta / distance; + // Normalize the delta to get the collision direction + float distance + = std::sqrt(closest_delta.x * closest_delta.x + closest_delta.y * closest_delta.y); + vec2 collision_normal = closest_delta / distance; - // Compute penetration depth - float penetration_depth = circle_collider.radius - distance; + // Compute penetration depth + float penetration_depth = circle_collider.radius - distance; - // Compute the resolution vector - vec2 resolution = collision_normal * penetration_depth; + // Compute the resolution vector + vec2 resolution = collision_normal * penetration_depth; - return resolution; + return resolution; } - -void CollisionSystem::determine_collision_handler(CollisionInfo& info){ +void CollisionSystem::determine_collision_handler(CollisionInfo & info) { // Check rigidbody type for static - if(info.this_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return; + if (info.this_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return; // If second body is static perform the static collision handler in this system - if(info.other_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){ + if (info.other_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) { static_collision_handler(info); - }; + }; // Call collision event for user CollisionEvent data(info); - EventManager::get_instance().trigger_event(data, info.this_collider.game_object_id); + EventManager::get_instance().trigger_event( + data, info.this_collider.game_object_id); } -void CollisionSystem::static_collision_handler(CollisionInfo& info){ - // Move object back using calculate move back value +void CollisionSystem::static_collision_handler(CollisionInfo & info) { + // Move object back using calculate move back value info.this_transform.position += info.resolution; // If bounce is enabled mirror velocity - if(info.this_rigidbody.data.elastisity_coefficient > 0) { - if(info.resolution_direction == Direction::BOTH) - { - info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient; - info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient; - } - else if(info.resolution_direction == Direction::Y_DIRECTION) { - info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient; - } - else if(info.resolution_direction == Direction::X_DIRECTION){ - info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient; + if (info.this_rigidbody.data.elastisity_coefficient > 0) { + if (info.resolution_direction == Direction::BOTH) { + info.this_rigidbody.data.linear_velocity.y + = -info.this_rigidbody.data.linear_velocity.y + * info.this_rigidbody.data.elastisity_coefficient; + info.this_rigidbody.data.linear_velocity.x + = -info.this_rigidbody.data.linear_velocity.x + * info.this_rigidbody.data.elastisity_coefficient; + } else if (info.resolution_direction == Direction::Y_DIRECTION) { + info.this_rigidbody.data.linear_velocity.y + = -info.this_rigidbody.data.linear_velocity.y + * info.this_rigidbody.data.elastisity_coefficient; + } else if (info.resolution_direction == Direction::X_DIRECTION) { + info.this_rigidbody.data.linear_velocity.x + = -info.this_rigidbody.data.linear_velocity.x + * info.this_rigidbody.data.elastisity_coefficient; } } // Stop movement if bounce is disabled else { - info.this_rigidbody.data.linear_velocity = {0,0}; + info.this_rigidbody.data.linear_velocity = {0, 0}; } } -std::vector> CollisionSystem::gather_collisions(std::vector & colliders) { - - +std::vector> +CollisionSystem::gather_collisions(std::vector & colliders) { + // TODO: // If no colliders skip // Check if colliders has rigidbody if not skip @@ -311,83 +354,103 @@ std::vector> collisions_ret; - //using visit to visit the variant to access the active and id. + std::vector> collisions_ret; + //using visit to visit the variant to access the active and id. for (size_t i = 0; i < colliders.size(); ++i) { for (size_t j = i + 1; j < colliders.size(); ++j) { - if(colliders[i].id == colliders[j].id) continue; - CollisionInternalType type = get_collider_type(colliders[i].collider,colliders[j].collider); - if(!get_collision({ - .collider = colliders[i].collider, - .transform = colliders[i].transform, - .rigidbody = colliders[i].rigidbody, + if (colliders[i].id == colliders[j].id) continue; + CollisionInternalType type + = get_collider_type(colliders[i].collider, colliders[j].collider); + if (!get_collision( + { + .collider = colliders[i].collider, + .transform = colliders[i].transform, + .rigidbody = colliders[i].rigidbody, }, { - .collider = colliders[j].collider, - .transform = colliders[j].transform, - .rigidbody = colliders[j].rigidbody, + .collider = colliders[j].collider, + .transform = colliders[j].transform, + .rigidbody = colliders[j].rigidbody, }, - type)) continue; - collisions_ret.emplace_back(colliders[i],colliders[j]); + type)) + continue; + collisions_ret.emplace_back(colliders[i], colliders[j]); } } - + return collisions_ret; } -CollisionSystem::CollisionInternalType CollisionSystem::get_collider_type(const collider_variant& collider1,const collider_variant& collider2) const{ - if(std::holds_alternative>(collider1)){ - if(std::holds_alternative>(collider2)) - { +CollisionSystem::CollisionInternalType +CollisionSystem::get_collider_type(const collider_variant & collider1, + const collider_variant & collider2) const { + if (std::holds_alternative>(collider1)) { + if (std::holds_alternative>(collider2)) { return CollisionInternalType::CIRCLE_CIRCLE; - } - else { + } else { return CollisionInternalType::CIRCLE_BOX; } - } - else { - if(std::holds_alternative>(collider2)) - { + } else { + if (std::holds_alternative>(collider2)) { return CollisionInternalType::BOX_CIRCLE; - } - else { + } else { return CollisionInternalType::BOX_BOX; } } } -bool CollisionSystem::get_collision(const CollisionInternal& first_info,const CollisionInternal& second_info, CollisionInternalType type) const{ +bool CollisionSystem::get_collision(const CollisionInternal & first_info, + const CollisionInternal & second_info, + CollisionInternalType type) const { switch (type) { - case CollisionInternalType::BOX_BOX: { - const BoxCollider & box_collider1 = std::get>(first_info.collider); - const BoxCollider & box_collider2 = std::get>(second_info.collider); - return this->get_box_box_collision(box_collider1,box_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + case CollisionInternalType::BOX_BOX: { + const BoxCollider & box_collider1 + = std::get>(first_info.collider); + const BoxCollider & box_collider2 + = std::get>(second_info.collider); + return this->get_box_box_collision(box_collider1, box_collider2, + first_info.transform, second_info.transform, + second_info.rigidbody, second_info.rigidbody); } case CollisionInternalType::BOX_CIRCLE: { - const BoxCollider & box_collider = std::get>(first_info.collider); - const CircleCollider & circle_collider = std::get>(second_info.collider); - return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + const BoxCollider & box_collider + = std::get>(first_info.collider); + const CircleCollider & circle_collider + = std::get>(second_info.collider); + return this->get_box_circle_collision( + box_collider, circle_collider, first_info.transform, second_info.transform, + second_info.rigidbody, second_info.rigidbody); } - case CollisionInternalType::CIRCLE_CIRCLE: { - const CircleCollider & circle_collider1 = std::get>(first_info.collider); - const CircleCollider & circle_collider2 = std::get>(second_info.collider); - return this->get_circle_circle_collision(circle_collider1,circle_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + case CollisionInternalType::CIRCLE_CIRCLE: { + const CircleCollider & circle_collider1 + = std::get>(first_info.collider); + const CircleCollider & circle_collider2 + = std::get>(second_info.collider); + return this->get_circle_circle_collision( + circle_collider1, circle_collider2, first_info.transform, + second_info.transform, second_info.rigidbody, second_info.rigidbody); } - case CollisionInternalType::CIRCLE_BOX: { - const CircleCollider & circle_collider = std::get>(first_info.collider); - const BoxCollider & box_collider = std::get>(second_info.collider); - return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + case CollisionInternalType::CIRCLE_BOX: { + const CircleCollider & circle_collider + = std::get>(first_info.collider); + const BoxCollider & box_collider + = std::get>(second_info.collider); + return this->get_box_circle_collision( + box_collider, circle_collider, first_info.transform, second_info.transform, + second_info.rigidbody, second_info.rigidbody); } } return false; } - -bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const -{ +bool CollisionSystem::get_box_box_collision(const BoxCollider & box1, const BoxCollider & box2, + const Transform & transform1, + const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = this->get_current_position(box1.offset,transform1,rigidbody1); - vec2 final_position2 = this->get_current_position(box2.offset,transform2,rigidbody2); + vec2 final_position1 = this->get_current_position(box1.offset, transform1, rigidbody1); + vec2 final_position2 = this->get_current_position(box2.offset, transform2, rigidbody2); // Calculate half-extents (half width and half height) float half_width1 = box1.dimensions.x / 2.0; @@ -396,13 +459,18 @@ bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCo float half_height2 = box2.dimensions.y / 2.0; // Check if the boxes overlap along the X and Y axes - return (final_position1.x + half_width1 > final_position2.x - half_width2 && - final_position1.x - half_width1 < final_position2.x + half_width2 && - final_position1.y + half_height1 > final_position2.y - half_height2 && - final_position1.y - half_height1 < final_position2.y + half_height2); + return (final_position1.x + half_width1 > final_position2.x - half_width2 + && final_position1.x - half_width1 < final_position2.x + half_width2 + && final_position1.y + half_height1 > final_position2.y - half_height2 + && final_position1.y - half_height1 < final_position2.y + half_height2); } -bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { +bool CollisionSystem::get_box_circle_collision(const BoxCollider & box1, + const CircleCollider & circle2, + const Transform & transform1, + const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const { // Get current positions of colliders vec2 final_position1 = this->get_current_position(box1.offset, transform1, rigidbody1); vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2); @@ -412,8 +480,10 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const Ci float half_height = box1.dimensions.y / 2.0; // Find the closest point on the box to the circle's center - float closest_x = std::max(final_position1.x - half_width, std::min(final_position2.x, final_position1.x + half_width)); - float closest_y = std::max(final_position1.y - half_height, std::min(final_position2.y, final_position1.y + half_height)); + float closest_x = std::max(final_position1.x - half_width, + std::min(final_position2.x, final_position1.x + half_width)); + float closest_y = std::max(final_position1.y - half_height, + std::min(final_position2.y, final_position1.y + half_height)); // Calculate the distance squared between the circle's center and the closest point on the box float distance_x = final_position2.x - closest_x; @@ -424,10 +494,15 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const Ci return distance_squared <= circle2.radius * circle2.radius; } -bool CollisionSystem::get_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { +bool CollisionSystem::get_circle_circle_collision(const CircleCollider & circle1, + const CircleCollider & circle2, + const Transform & transform1, + const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = this->get_current_position(circle1.offset,transform1,rigidbody1); - vec2 final_position2 = this->get_current_position(circle2.offset,transform2,rigidbody2); + vec2 final_position1 = this->get_current_position(circle1.offset, transform1, rigidbody1); + vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2); float distance_x = final_position1.x - final_position2.x; float distance_y = final_position1.y - final_position2.y; @@ -440,7 +515,9 @@ bool CollisionSystem::get_circle_circle_collision(const CircleCollider& circle1, return distance_squared <= radius_sum * radius_sum; } -vec2 CollisionSystem::get_current_position(const vec2& collider_offset, const Transform& transform, const Rigidbody& rigidbody) const { +vec2 CollisionSystem::get_current_position(const vec2 & collider_offset, + const Transform & transform, + const Rigidbody & rigidbody) const { // Get the rotation in radians float radians1 = transform.rotation * (M_PI / 180.0); @@ -448,10 +525,11 @@ vec2 CollisionSystem::get_current_position(const vec2& collider_offset, const Tr vec2 total_offset = (rigidbody.data.offset + collider_offset) * transform.scale; // Rotate - float rotated_total_offset_x1 = total_offset.x * cos(radians1) - total_offset.y * sin(radians1); - float rotated_total_offset_y1 = total_offset.x * sin(radians1) + total_offset.y * cos(radians1); + float rotated_total_offset_x1 + = total_offset.x * cos(radians1) - total_offset.y * sin(radians1); + float rotated_total_offset_y1 + = total_offset.x * sin(radians1) + total_offset.y * cos(radians1); // Final positions considering scaling and rotation - return(transform.position + vec2(rotated_total_offset_x1, rotated_total_offset_y1)); - + return (transform.position + vec2(rotated_total_offset_x1, rotated_total_offset_y1)); } diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 85ae5ad..6b5a4bb 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -1,38 +1,37 @@ #pragma once -#include -#include #include +#include +#include -#include "api/Rigidbody.h" -#include "api/Transform.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" #include "api/Metadata.h" +#include "api/Rigidbody.h" +#include "api/Transform.h" #include "api/Vector2.h" #include "Collider.h" #include "System.h" - namespace crepe { - //! A system responsible for detecting and handling collisions between colliders. class CollisionSystem : public System { public: using System::System; + private: - //! A variant type that can hold either a BoxCollider or a CircleCollider. - using collider_variant = std::variant, std::reference_wrapper>; + using collider_variant = std::variant, + std::reference_wrapper>; //! Enum representing the types of collider pairs for collision detection. enum class CollisionInternalType { - BOX_BOX, - CIRCLE_CIRCLE, - BOX_CIRCLE, - CIRCLE_BOX, + BOX_BOX, + CIRCLE_CIRCLE, + BOX_CIRCLE, + CIRCLE_BOX, }; /** @@ -45,21 +44,21 @@ private: */ struct CollisionInternal { game_object_id_t id = 0; - collider_variant collider; - Transform& transform; - Rigidbody& rigidbody; + collider_variant collider; + Transform & transform; + Rigidbody & rigidbody; }; - + //! Enum representing movement directions during collision resolution. enum class Direction { //! No movement required. - NONE, + NONE, //! Movement in the X direction. - X_DIRECTION, + X_DIRECTION, //! Movement in the Y direction. - Y_DIRECTION, + Y_DIRECTION, //! Movement in both X and Y directions. - BOTH + BOTH }; public: @@ -68,15 +67,15 @@ public: * * Includes information about the colliding objects and the resolution data for handling the collision. */ - struct CollisionInfo{ - Collider& this_collider; - Transform& this_transform; - Rigidbody& this_rigidbody; - Metadata& this_metadata; - Collider& other_collider; - Transform& other_transform; - Rigidbody& other_rigidbody; - Metadata& other_metadata; + struct CollisionInfo { + Collider & this_collider; + Transform & this_transform; + Rigidbody & this_rigidbody; + Metadata & this_metadata; + Collider & other_collider; + Transform & other_transform; + Rigidbody & other_rigidbody; + Metadata & other_metadata; //! The resolution vector for the collision. vec2 resolution; //! The direction of movement for resolving the collision. @@ -84,11 +83,10 @@ public: }; public: - //! Updates the collision system by checking for collisions between colliders and handling them. void update() override; -private: +private: /** * \brief Determines the type of collider pair from two colliders. * @@ -98,7 +96,8 @@ private: * \param collider2 Second collider variant (BoxCollider or CircleCollider). * \return The combined type of the two colliders. */ - CollisionInternalType get_collider_type(const collider_variant& collider1,const collider_variant& collider2) const; + CollisionInternalType get_collider_type(const collider_variant & collider1, + const collider_variant & collider2) const; /** * \brief Calculates the current position of a collider. @@ -110,10 +109,10 @@ private: * \param rigidbody The Rigidbody of the associated game object. * \return The calculated position of the collider. */ - vec2 get_current_position(const vec2& collider_offset, const Transform& transform, const Rigidbody& rigidbody) const; + vec2 get_current_position(const vec2 & collider_offset, const Transform & transform, + const Rigidbody & rigidbody) const; private: - /** * \brief Handles collision resolution between two colliders. * @@ -122,7 +121,7 @@ private: * \param data1 Collision data for the first collider. * \param data2 Collision data for the second collider. */ - void collision_handler_request(CollisionInternal& data1,CollisionInternal& data2); + void collision_handler_request(CollisionInternal & data1, CollisionInternal & data2); /** * \brief Resolves collision between two colliders and calculates the movement required. @@ -134,7 +133,9 @@ private: * \param type The type of collider pair. * \return A pair containing the resolution vector and direction for the first collider. */ - std::pair collision_handler(CollisionInternal& data1,CollisionInternal& data2 ,CollisionInternalType type); + std::pair collision_handler(CollisionInternal & data1, + CollisionInternal & data2, + CollisionInternalType type); /** * \brief Calculates the resolution vector for two BoxColliders. @@ -147,7 +148,9 @@ private: * \param position2 The position of the second BoxCollider. * \return The resolution vector for the collision. */ - vec2 get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,const vec2& position1,const vec2& position2) const; + vec2 get_box_box_resolution(const BoxCollider & box_collider1, + const BoxCollider & box_collider2, const vec2 & position1, + const vec2 & position2) const; /** * \brief Calculates the resolution vector for two CircleCollider. @@ -160,7 +163,10 @@ private: * \param position2 The position of the second CircleCollider. * \return The resolution vector for the collision. */ - vec2 get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, const vec2& final_position1, const vec2& final_position2) const; + vec2 get_circle_circle_resolution(const CircleCollider & circle_collider1, + const CircleCollider & circle_collider2, + const vec2 & final_position1, + const vec2 & final_position2) const; /** * \brief Calculates the resolution vector for two CircleCollider. @@ -173,7 +179,10 @@ private: * \param box_position The position of the BocCollider. * \return The resolution vector for the collision. */ - vec2 get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, const vec2& circle_position, const vec2& box_position) const; + vec2 get_circle_box_resolution(const CircleCollider & circle_collider, + const BoxCollider & box_collider, + const vec2 & circle_position, + const vec2 & box_position) const; /** * \brief Determines the appropriate collision handler for a collision. @@ -182,7 +191,7 @@ private: * * \param info Collision information containing data about both colliders. */ - void determine_collision_handler(CollisionInfo& info); + void determine_collision_handler(CollisionInfo & info); /** * \brief Handles collisions involving static objects. @@ -191,9 +200,9 @@ private: * * \param info Collision information containing data about both colliders. */ - void static_collision_handler(CollisionInfo& info); + void static_collision_handler(CollisionInfo & info); + private: - /** * \brief Checks for collisions between colliders. * @@ -202,7 +211,8 @@ private: * \param colliders A collection of all active colliders. * \return A list of collision pairs with their associated data. */ - std::vector> gather_collisions(std::vector & colliders); + std::vector> + gather_collisions(std::vector & colliders); /** * \brief Checks for collision between two colliders. @@ -214,8 +224,10 @@ private: * \param type The type of collider pair. * \return True if a collision is detected, otherwise false. */ - bool get_collision(const CollisionInternal& first_info,const CollisionInternal& second_info, CollisionInternalType type) const; - + bool get_collision(const CollisionInternal & first_info, + const CollisionInternal & second_info, + CollisionInternalType type) const; + /** * \brief Detects collisions between two BoxColliders. * @@ -227,8 +239,11 @@ private: * \param rigidbody2 Rigidbody of the second object. * \return True if a collision is detected, otherwise false. */ - bool get_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const; - + bool get_box_box_collision(const BoxCollider & box1, const BoxCollider & box2, + const Transform & transform1, const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const; + /** * \brief Check collision for box on circle collider * @@ -240,7 +255,10 @@ private: * \param rigidbody2 Rigidbody of the second object. * \return True if a collision is detected, otherwise false. */ - bool get_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const; + bool get_box_circle_collision(const BoxCollider & box1, const CircleCollider & circle2, + const Transform & transform1, const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const; /** * \brief Check collision for circle on circle collider @@ -255,7 +273,12 @@ private: * * \return status of collision */ - bool get_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const; + bool get_circle_circle_collision(const CircleCollider & circle1, + const CircleCollider & circle2, + const Transform & transform1, + const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const; }; } // namespace crepe diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index b5da042..b3adfa1 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -32,10 +32,13 @@ void PhysicsSystem::update() { } // Add damping if (rigidbody.data.angular_velocity_coefficient > 0) { - rigidbody.data.angular_velocity *= rigidbody.data.angular_velocity_coefficient; + rigidbody.data.angular_velocity + *= rigidbody.data.angular_velocity_coefficient; } - if (rigidbody.data.linear_velocity_coefficient.x > 0 && rigidbody.data.linear_velocity_coefficient.y > 0) { - rigidbody.data.linear_velocity *= rigidbody.data.linear_velocity_coefficient; + if (rigidbody.data.linear_velocity_coefficient.x > 0 + && rigidbody.data.linear_velocity_coefficient.y > 0) { + rigidbody.data.linear_velocity + *= rigidbody.data.linear_velocity_coefficient; } // Max velocity check diff --git a/src/example/game.cpp b/src/example/game.cpp index de08a22..70c562e 100644 --- a/src/example/game.cpp +++ b/src/example/game.cpp @@ -1,77 +1,84 @@ -#include -#include -#include #include #include -#include #include -#include -#include -#include #include #include +#include #include +#include +#include +#include +#include +#include +#include using namespace crepe; using namespace std; class MyScript : public Script { - bool oncollision(const CollisionEvent& test) { + bool oncollision(const CollisionEvent & test) { Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id); return true; } void init() { - subscribe([this](const CollisionEvent& ev) -> bool { - return this->oncollision(ev); - }); + subscribe( + [this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); }); } void update() { // Retrieve component from the same GameObject this script is on } }; - class ConcreteScene1 : public Scene { public: using Scene::Scene; void load_scene() { - ComponentManager & mgr = this->component_manager; - Color color(0, 0, 0, 255); + ComponentManager & mgr = this->component_manager; + Color color(0, 0, 0, 255); - float screen_size_width = 640; - float screen_size_height = 480; - float world_collider = 1000; - //define playable world - GameObject world = mgr.new_object("Name", "Tag", vec2{screen_size_width/2, screen_size_height/2}, 0, 1); - world.add_component(Rigidbody::Data{ - .mass = 0, - .gravity_scale = 0, - .body_type = Rigidbody::BodyType::STATIC, - .constraints = {0, 0, 0}, - .offset = {0,0} - }); - world.add_component(vec2{0, 0-(screen_size_height/2+world_collider/2)}, vec2{world_collider, world_collider});; // Top - world.add_component(vec2{0, screen_size_height/2+world_collider/2}, vec2{world_collider, world_collider}); // Bottom - world.add_component(vec2{0-(screen_size_width/2+world_collider/2), 0}, vec2{world_collider, world_collider}); // Left - world.add_component(vec2{screen_size_width/2+world_collider/2, 0}, vec2{world_collider, world_collider}); // right - world.add_component(Color::WHITE, ivec2{640, 480},vec2{640, 480}, 1.0f); + float screen_size_width = 640; + float screen_size_height = 480; + float world_collider = 1000; + //define playable world + GameObject world = mgr.new_object( + "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1); + world.add_component( + Rigidbody::Data{.mass = 0, + .gravity_scale = 0, + .body_type = Rigidbody::BodyType::STATIC, + .constraints = {0, 0, 0}, + .offset = {0, 0}}); + world.add_component( + vec2{0, 0 - (screen_size_height / 2 + world_collider / 2)}, + vec2{world_collider, world_collider}); + ; // Top + world.add_component(vec2{0, screen_size_height / 2 + world_collider / 2}, + vec2{world_collider, world_collider}); // Bottom + world.add_component( + vec2{0 - (screen_size_width / 2 + world_collider / 2), 0}, + vec2{world_collider, world_collider}); // Left + world.add_component(vec2{screen_size_width / 2 + world_collider / 2, 0}, + vec2{world_collider, world_collider}); // right + world.add_component(Color::WHITE, ivec2{640, 480}, vec2{640, 480}, 1.0f); - GameObject game_object1 = mgr.new_object("Name", "Tag", vec2{screen_size_width/2, screen_size_height/2}, 0, 1); - game_object1.add_component(Rigidbody::Data{ - .mass = 1, - .gravity_scale = 0.01, - .body_type = Rigidbody::BodyType::DYNAMIC, - .linear_velocity = {1,1}, - .constraints = {0, 0, 0}, - .elastisity_coefficient = 1, - .offset = {0,0}, - }); - game_object1.add_component(vec2{0, 0}, vec2{20, 20}); - game_object1.add_component().set_script(); - auto img = Texture("asset/texture/green_square.png"); - game_object1.add_component(img, color, Sprite::FlipSettings{false, false}, 1, 1, 20); + GameObject game_object1 = mgr.new_object( + "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1); + game_object1.add_component(Rigidbody::Data{ + .mass = 1, + .gravity_scale = 0.01, + .body_type = Rigidbody::BodyType::DYNAMIC, + .linear_velocity = {1, 1}, + .constraints = {0, 0, 0}, + .elastisity_coefficient = 1, + .offset = {0, 0}, + }); + game_object1.add_component(vec2{0, 0}, vec2{20, 20}); + game_object1.add_component().set_script(); + auto img = Texture("asset/texture/green_square.png"); + game_object1.add_component(img, color, Sprite::FlipSettings{false, false}, 1, + 1, 20); } string get_name() const { return "scene1"; } diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index fec42f3..74edaf7 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -26,22 +26,19 @@ using namespace testing; class CollisionHandler : public Script { public: int box_id; - function test_fn = [](const CollisionEvent & ev) { }; + function test_fn = [](const CollisionEvent & ev) {}; - CollisionHandler(int box_id) { - this->box_id = box_id; - } + CollisionHandler(int box_id) { this->box_id = box_id; } - bool on_collision(const CollisionEvent& ev) { + bool on_collision(const CollisionEvent & ev) { //Log::logf("Box {} script on_collision()", box_id); test_fn(ev); return true; } void init() { - subscribe([this](const CollisionEvent& ev) -> bool { - return this->on_collision(ev); - }); + subscribe( + [this](const CollisionEvent & ev) -> bool { return this->on_collision(ev); }); } void update() { // Retrieve component from the same GameObject this script is on @@ -54,18 +51,18 @@ public: CollisionSystem collision_sys{mgr}; ScriptSystem script_sys{mgr}; - GameObject world = mgr.new_object("world","",{50,50}); - GameObject game_object1 = mgr.new_object("object1", "", { 50, 50}); - GameObject game_object2 = mgr.new_object("object2", "", { 50, 30}); + GameObject world = mgr.new_object("world", "", {50, 50}); + GameObject game_object1 = mgr.new_object("object1", "", {50, 50}); + GameObject game_object2 = mgr.new_object("object2", "", {50, 30}); CollisionHandler * script_object1_ref = nullptr; CollisionHandler * script_object2_ref = nullptr; - + void SetUp() override { world.add_component(Rigidbody::Data{ // TODO: remove unrelated properties: .body_type = Rigidbody::BodyType::STATIC, - .offset = {0,0}, + .offset = {0, 0}, }); // Create a box with an inner size of 10x10 units world.add_component(vec2{0, -100}, vec2{100, 100}); // Top @@ -77,28 +74,30 @@ public: .mass = 1, .gravity_scale = 0.01, .body_type = Rigidbody::BodyType::DYNAMIC, - .linear_velocity = {0,0}, + .linear_velocity = {0, 0}, .constraints = {0, 0, 0}, .elastisity_coefficient = 1, - .offset = {0,0}, + .offset = {0, 0}, }); game_object1.add_component(vec2{0, 0}, vec2{10, 10}); - BehaviorScript & script_object1 = game_object1.add_component().set_script(1); - script_object1_ref = static_cast(script_object1.script.get()); + BehaviorScript & script_object1 + = game_object1.add_component().set_script(1); + script_object1_ref = static_cast(script_object1.script.get()); ASSERT_NE(script_object1_ref, nullptr); - + game_object2.add_component(Rigidbody::Data{ .mass = 1, .gravity_scale = 0.01, .body_type = Rigidbody::BodyType::DYNAMIC, - .linear_velocity = {0,0}, + .linear_velocity = {0, 0}, .constraints = {0, 0, 0}, .elastisity_coefficient = 1, - .offset = {0,0}, + .offset = {0, 0}, }); game_object2.add_component(vec2{0, 0}, vec2{10, 10}); - BehaviorScript & script_object2 = game_object2.add_component().set_script(2); - script_object2_ref = static_cast(script_object2.script.get()); + BehaviorScript & script_object2 + = game_object2.add_component().set_script(2); + script_object2_ref = static_cast(script_object2.script.get()); ASSERT_NE(script_object2_ref, nullptr); // Ensure Script::init() is called on all BehaviorScript instances @@ -139,7 +138,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both_no_velocity) { }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {50,30}; + tf.position = {50, 30}; collision_sys.update(); EXPECT_TRUE(collision_happend); } @@ -151,18 +150,20 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction_no_velocity) { EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, 0); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 0); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::X_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {45,30}; + tf.position = {45, 30}; collision_sys.update(); EXPECT_TRUE(collision_happend); } @@ -174,18 +175,20 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction_no_velocity) { EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 0); EXPECT_EQ(ev.info.resolution.y, -5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 0); EXPECT_EQ(ev.info.resolution.y, 5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::Y_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {50,25}; + tf.position = {50, 25}; collision_sys.update(); EXPECT_TRUE(collision_happend); } @@ -208,11 +211,11 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both) { }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {50,30}; + tf.position = {50, 30}; Rigidbody & rg1 = this->mgr.get_components_by_id(1).front().get(); - rg1.data.linear_velocity = {10,10}; + rg1.data.linear_velocity = {10, 10}; Rigidbody & rg2 = this->mgr.get_components_by_id(2).front().get(); - rg2.data.linear_velocity = {10,10}; + rg2.data.linear_velocity = {10, 10}; collision_sys.update(); EXPECT_TRUE(collision_happend); } @@ -224,22 +227,24 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) { EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::X_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {45,30}; + tf.position = {45, 30}; Rigidbody & rg1 = this->mgr.get_components_by_id(1).front().get(); - rg1.data.linear_velocity = {10,10}; + rg1.data.linear_velocity = {10, 10}; Rigidbody & rg2 = this->mgr.get_components_by_id(2).front().get(); - rg2.data.linear_velocity = {10,10}; + rg2.data.linear_velocity = {10, 10}; collision_sys.update(); EXPECT_TRUE(collision_happend); } @@ -251,27 +256,28 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction) { EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::Y_DIRECTION); }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {50,25}; + tf.position = {50, 25}; Rigidbody & rg1 = this->mgr.get_components_by_id(1).front().get(); - rg1.data.linear_velocity = {10,10}; + rg1.data.linear_velocity = {10, 10}; Rigidbody & rg2 = this->mgr.get_components_by_id(2).front().get(); - rg2.data.linear_velocity = {10,10}; + rg2.data.linear_velocity = {10, 10}; collision_sys.update(); EXPECT_TRUE(collision_happend); } - TEST_F(CollisionTest, collision_box_box_static_both) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { @@ -287,7 +293,7 @@ TEST_F(CollisionTest, collision_box_box_static_both) { }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {50,30}; + tf.position = {50, 30}; Rigidbody & rg2 = this->mgr.get_components_by_id(2).front().get(); rg2.data.body_type = crepe::Rigidbody::BodyType::STATIC; collision_sys.update(); @@ -301,7 +307,8 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) { EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { // is static should not be called @@ -309,9 +316,9 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) { }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {45,30}; + tf.position = {45, 30}; Rigidbody & rg1 = this->mgr.get_components_by_id(1).front().get(); - rg1.data.linear_velocity = {10,10}; + rg1.data.linear_velocity = {10, 10}; Rigidbody & rg2 = this->mgr.get_components_by_id(2).front().get(); rg2.data.body_type = crepe::Rigidbody::BodyType::STATIC; collision_sys.update(); @@ -325,7 +332,8 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) { EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); - EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); + EXPECT_EQ(ev.info.resolution_direction, + crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { // is static should not be called @@ -333,24 +341,24 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) { }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {50,25}; + tf.position = {50, 25}; Rigidbody & rg1 = this->mgr.get_components_by_id(1).front().get(); - rg1.data.linear_velocity = {10,10}; + rg1.data.linear_velocity = {10, 10}; Rigidbody & rg2 = this->mgr.get_components_by_id(2).front().get(); rg2.data.body_type = crepe::Rigidbody::BodyType::STATIC; collision_sys.update(); EXPECT_TRUE(collision_happend); } -TEST_F(CollisionTest, collision_box_box_static_multiple) {//todo check visually +TEST_F(CollisionTest, collision_box_box_static_multiple) { //todo check visually bool collision_happend = false; float offset_value = 0; float resolution = 0; script_object1_ref->test_fn = [&](const CollisionEvent & ev) { collision_happend = true; EXPECT_EQ(ev.info.this_collider.game_object_id, 1); - EXPECT_EQ(ev.info.this_collider.offset.x , offset_value); - EXPECT_EQ(ev.info.resolution.x , resolution); + EXPECT_EQ(ev.info.this_collider.offset.x, offset_value); + EXPECT_EQ(ev.info.resolution.x, resolution); }; script_object2_ref->test_fn = [&](const CollisionEvent & ev) { // is static should not be called @@ -358,20 +366,20 @@ TEST_F(CollisionTest, collision_box_box_static_multiple) {//todo check visually }; EXPECT_FALSE(collision_happend); Transform & tf = this->mgr.get_components_by_id(1).front().get(); - tf.position = {45,30}; + tf.position = {45, 30}; Rigidbody & rg1 = this->mgr.get_components_by_id(1).front().get(); - rg1.data.linear_velocity = {10,10}; + rg1.data.linear_velocity = {10, 10}; Rigidbody & rg2 = this->mgr.get_components_by_id(2).front().get(); rg2.data.body_type = crepe::Rigidbody::BodyType::STATIC; BoxCollider & bxc = this->mgr.get_components_by_id(1).front().get(); - bxc.offset = {5,0}; + bxc.offset = {5, 0}; this->game_object1.add_component(vec2{-5, 0}, vec2{10, 10}); offset_value = 5; resolution = 10; collision_sys.update(); offset_value = -5; resolution = 10; - tf.position = {55,30}; + tf.position = {55, 30}; collision_sys.update(); EXPECT_TRUE(collision_happend); } diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index fa0f5f3..d2f219e 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -1,8 +1,8 @@ #include "system/ParticleSystem.h" #include "system/PhysicsSystem.h" #include "system/RenderSystem.h" -#include #include +#include #include #define private public @@ -12,10 +12,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -27,14 +27,13 @@ using namespace crepe; using namespace testing; class TestScript : public Script { - bool oncollision(const CollisionEvent& test) { + bool oncollision(const CollisionEvent & test) { Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id); return true; } void init() { - subscribe([this](const CollisionEvent& ev) -> bool { - return this->oncollision(ev); - }); + subscribe( + [this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); }); } void update() { // Retrieve component from the same GameObject this script is on @@ -52,10 +51,9 @@ public: const int average = 5; // Maximum duration to stop test const std::chrono::microseconds duration = 16000us; - ComponentManager mgr; - // Add system used for profling tests + // Add system used for profling tests CollisionSystem collision_sys{mgr}; PhysicsSystem physics_sys{mgr}; ParticleSystem particle_sys{mgr}; @@ -67,12 +65,11 @@ public: int game_object_count = 0; std::chrono::microseconds total_time = 0us; - void SetUp() override { - - GameObject do_not_use = mgr.new_object("DO_NOT_USE","",{0,0}); - do_not_use.add_component(Color::WHITE, ivec2{1080, 720}, - vec2{2000, 2000}, 1.0f); + + GameObject do_not_use = mgr.new_object("DO_NOT_USE", "", {0, 0}); + do_not_use.add_component(Color::WHITE, ivec2{1080, 720}, vec2{2000, 2000}, + 1.0f); // initialize systems here: //calls init script_sys.update(); @@ -82,11 +79,12 @@ public: // Helper function to time an update call and store its duration template - std::chrono::microseconds time_function(const std::string& name, Func&& func) { + std::chrono::microseconds time_function(const std::string & name, Func && func) { auto start = std::chrono::steady_clock::now(); func(); auto end = std::chrono::steady_clock::now(); - std::chrono::microseconds duration = std::chrono::duration_cast(end - start); + std::chrono::microseconds duration + = std::chrono::duration_cast(end - start); timings[name] += duration; return duration; } @@ -95,8 +93,10 @@ public: std::chrono::microseconds run_all_systems() { std::chrono::microseconds total_microseconds = 0us; total_microseconds += time_function("PhysicsSystem", [&]() { physics_sys.update(); }); - total_microseconds += time_function("CollisionSystem", [&]() { collision_sys.update(); }); - total_microseconds += time_function("ParticleSystem", [&]() { particle_sys.update(); }); + total_microseconds + += time_function("CollisionSystem", [&]() { collision_sys.update(); }); + total_microseconds + += time_function("ParticleSystem", [&]() { particle_sys.update(); }); total_microseconds += time_function("RenderSystem", [&]() { render_sys.update(); }); return total_microseconds; } @@ -104,34 +104,33 @@ public: // Print timings of all functions void log_timings() const { std::string result = "\nFunction timings:\n"; - - for (const auto& [name, duration] : timings) { - result += name + " took " + std::to_string(duration.count() / 1000.0 / average) + " ms (" + - std::to_string(duration.count() / average) + " µs).\n"; - } - - result += "Total time: " + std::to_string(this->total_time.count() / 1000.0 / average) + " ms (" + - std::to_string(this->total_time.count() / average) + " µs)\n"; - - result += "Amount of gameobjects: " + std::to_string(game_object_count) + "\n"; - - GTEST_LOG_(INFO) << result; + + for (const auto & [name, duration] : timings) { + result += name + " took " + std::to_string(duration.count() / 1000.0 / average) + + " ms (" + std::to_string(duration.count() / average) + " µs).\n"; + } + + result += "Total time: " + std::to_string(this->total_time.count() / 1000.0 / average) + + " ms (" + std::to_string(this->total_time.count() / average) + " µs)\n"; + + result += "Amount of gameobjects: " + std::to_string(game_object_count) + "\n"; + + GTEST_LOG_(INFO) << result; } void clear_timings() { - for (auto& [key, value] : timings) { - value = std::chrono::microseconds(0); + for (auto & [key, value] : timings) { + value = std::chrono::microseconds(0); } } }; TEST_F(Profiling, Profiling_1) { - while (this->total_time/this->average < this->duration) { - + while (this->total_time / this->average < this->duration) { { //define gameobject used for testing - GameObject gameobject = mgr.new_object("gameobject","",{0,0}); + GameObject gameobject = mgr.new_object("gameobject", "", {0, 0}); } this->game_object_count++; @@ -143,18 +142,19 @@ TEST_F(Profiling, Profiling_1) { this->total_time += run_all_systems(); } - if(this->game_object_count >= this->max_gameobject_count) break; + if (this->game_object_count >= this->max_gameobject_count) break; } log_timings(); EXPECT_GE(this->game_object_count, this->min_gameobject_count); } TEST_F(Profiling, Profiling_2) { - while (this->total_time/this->average < this->duration) { - + while (this->total_time / this->average < this->duration) { + { //define gameobject used for testing - GameObject gameobject = mgr.new_object("gameobject","",{static_cast(game_object_count*2),0}); + GameObject gameobject = mgr.new_object( + "gameobject", "", {static_cast(game_object_count * 2), 0}); gameobject.add_component(Rigidbody::Data{ .gravity_scale = 0.0, .body_type = Rigidbody::BodyType::STATIC, @@ -163,7 +163,8 @@ TEST_F(Profiling, Profiling_2) { gameobject.add_component().set_script(); Color color(0, 0, 0, 0); auto img = Texture("asset/texture/green_square.png"); - Sprite & test_sprite = gameobject.add_component(img, color, Sprite::FlipSettings{false, false}, 1, 1, 500); + Sprite & test_sprite = gameobject.add_component( + img, color, Sprite::FlipSettings{false, false}, 1, 1, 500); } this->game_object_count++; @@ -174,50 +175,52 @@ TEST_F(Profiling, Profiling_2) { this->total_time += run_all_systems(); } - if(this->game_object_count >= this->max_gameobject_count) break; + if (this->game_object_count >= this->max_gameobject_count) break; } log_timings(); EXPECT_GE(this->game_object_count, this->min_gameobject_count); } TEST_F(Profiling, Profiling_3) { - while (this->total_time/this->average < this->duration) { - + while (this->total_time / this->average < this->duration) { + { //define gameobject used for testing - GameObject gameobject = mgr.new_object("gameobject","",{static_cast(game_object_count*2),0}); + GameObject gameobject = mgr.new_object( + "gameobject", "", {static_cast(game_object_count * 2), 0}); gameobject.add_component(Rigidbody::Data{ - .gravity_scale = 0, - .body_type = Rigidbody::BodyType::STATIC, + .gravity_scale = 0, + .body_type = Rigidbody::BodyType::STATIC, }); gameobject.add_component(vec2{0, 0}, 1, 1); gameobject.add_component().set_script(); Color color(0, 0, 0, 0); auto img = Texture("asset/texture/green_square.png"); - Sprite & test_sprite = gameobject.add_component(img, color, Sprite::FlipSettings{false, false}, 1, 1, 500); + Sprite & test_sprite = gameobject.add_component( + img, color, Sprite::FlipSettings{false, false}, 1, 1, 500); auto & test = gameobject.add_component(ParticleEmitter::Data{ - .max_particles = 10, - .emission_rate = 100, - .end_lifespan = 100000, - .boundary{ - .width = 1000, - .height = 1000, - .offset = vec2{0, 0}, - .reset_on_exit = false, - }, - .sprite = test_sprite, - }); + .max_particles = 10, + .emission_rate = 100, + .end_lifespan = 100000, + .boundary{ + .width = 1000, + .height = 1000, + .offset = vec2{0, 0}, + .reset_on_exit = false, + }, + .sprite = test_sprite, + }); } render_sys.update(); this->game_object_count++; - + this->total_time = 0us; clear_timings(); for (int amount = 0; amount < this->average; amount++) { this->total_time += run_all_systems(); } - if(this->game_object_count >= this->max_gameobject_count) break; + if (this->game_object_count >= this->max_gameobject_count) break; } log_timings(); EXPECT_GE(this->game_object_count, this->min_gameobject_count); -- cgit v1.2.3