diff options
-rw-r--r-- | src/crepe/api/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/crepe/api/Config.h | 2 | ||||
-rw-r--r-- | src/crepe/api/Rigidbody.h | 4 | ||||
-rw-r--r-- | src/crepe/api/Scene.cpp | 15 | ||||
-rw-r--r-- | src/crepe/api/Scene.h | 38 | ||||
-rw-r--r-- | src/crepe/api/Scene.hpp | 19 | ||||
-rw-r--r-- | src/crepe/manager/LoopTimerManager.cpp | 2 | ||||
-rw-r--r-- | src/crepe/manager/LoopTimerManager.h | 8 | ||||
-rw-r--r-- | src/crepe/system/AISystem.cpp | 10 | ||||
-rw-r--r-- | src/crepe/system/AnimatorSystem.cpp | 5 | ||||
-rw-r--r-- | src/crepe/system/CollisionSystem.cpp | 76 | ||||
-rw-r--r-- | src/crepe/system/PhysicsSystem.cpp | 131 | ||||
-rw-r--r-- | src/example/AITest.cpp | 24 | ||||
-rw-r--r-- | src/test/CollisionTest.cpp | 12 | ||||
-rw-r--r-- | src/test/LoopTimerTest.cpp | 18 | ||||
-rw-r--r-- | src/test/PhysicsTest.cpp | 46 | ||||
-rw-r--r-- | src/test/SceneManagerTest.cpp | 22 |
17 files changed, 279 insertions, 155 deletions
diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index fb11c8d..8f84f06 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -20,6 +20,7 @@ target_sources(crepe PUBLIC Button.cpp UIObject.cpp AI.cpp + Scene.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -36,6 +37,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Vector2.hpp Color.h Scene.h + Scene.hpp Metadata.h Camera.h Animator.h diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 6472270..ca2d3f1 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -53,7 +53,7 @@ struct Config final { * * Gravity value of game. */ - double gravity = 1; + float gravity = 10; } physics; //! default window settings diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 40c6bf1..b08c8db 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -53,7 +53,7 @@ public: */ struct Data { //! objects mass - float mass = 0.0; + float mass = 1; /** * \brief Gravity scale factor. * @@ -79,7 +79,7 @@ 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}; + float max_linear_velocity = INFINITY; //! Linear velocity coefficient. This scales the object's velocity for adjustment or damping. vec2 linear_velocity_coefficient = {1, 1}; //! \} diff --git a/src/crepe/api/Scene.cpp b/src/crepe/api/Scene.cpp new file mode 100644 index 0000000..ad729d2 --- /dev/null +++ b/src/crepe/api/Scene.cpp @@ -0,0 +1,15 @@ +#include "Scene.h" + +using namespace crepe; + +SaveManager & Scene::get_save_manager() const { return mediator->save_manager; } + +GameObject Scene::new_object(const std::string & name, const std::string & tag, + const vec2 & position, double rotation, double scale) { + // Forward the call to ComponentManager's new_object method + return mediator->component_manager->new_object(name, tag, position, rotation, scale); +} + +void Scene::set_persistent(const Asset & asset, bool persistent) { + mediator->resource_manager->set_persistent(asset, persistent); +} diff --git a/src/crepe/api/Scene.h b/src/crepe/api/Scene.h index ba9bb76..dcca9d4 100644 --- a/src/crepe/api/Scene.h +++ b/src/crepe/api/Scene.h @@ -2,13 +2,19 @@ #include <string> +#include "../manager/ComponentManager.h" #include "../manager/Mediator.h" +#include "../manager/ResourceManager.h" +#include "../util/Log.h" #include "../util/OptionalRef.h" +#include "GameObject.h" + namespace crepe { class SceneManager; class ComponentManager; +class Asset; /** * \brief Represents a Scene @@ -38,7 +44,7 @@ public: // TODO: Late references should ALWAYS be private! This is currently kept as-is so unit tests // keep passing, but this reference should not be directly accessible by the user!!! -protected: +private: /** * \name Late references * @@ -53,6 +59,36 @@ protected: //! Mediator reference OptionalRef<Mediator> mediator; //! \} + +protected: + /** + * \brief Retrieve the reference to the SaveManager instance + * + * \returns A reference to the SaveManager instance held by the Mediator. + */ + SaveManager & get_save_manager() const; + + //! \copydoc ComponentManager::new_object + GameObject new_object(const std::string & name, const std::string & tag = "", + const vec2 & position = {0, 0}, double rotation = 0, + double scale = 1); + + //! \copydoc ResourceManager::set_persistent + void set_persistent(const Asset & asset, bool persistent); + /** + * \name Logging functions + * \see Log + * \{ + */ + //! \copydoc Log::logf + template <class... Args> + void logf(const Log::Level & level, std::format_string<Args...> fmt, Args &&... args); + //! \copydoc Log::logf + template <class... Args> + void logf(std::format_string<Args...> fmt, Args &&... args); + //! \} }; } // namespace crepe + +#include "Scene.hpp" diff --git a/src/crepe/api/Scene.hpp b/src/crepe/api/Scene.hpp new file mode 100644 index 0000000..14635df --- /dev/null +++ b/src/crepe/api/Scene.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "../util/Log.h" + +#include "Scene.h" + +namespace crepe { + +template <class... Args> +void Scene::logf(const Log::Level & level, std::format_string<Args...> fmt, Args &&... args) { + Log::logf(level, fmt, std::forward<Args>(args)...); +} + +template <class... Args> +void Scene::logf(std::format_string<Args...> fmt, Args &&... args) { + Log::logf(fmt, std::forward<Args>(args)...); +} + +} // namespace crepe diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp index 9819632..a6e4788 100644 --- a/src/crepe/manager/LoopTimerManager.cpp +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -31,7 +31,7 @@ void LoopTimerManager::update() { this->delta_time = this->maximum_delta_time; } if (this->delta_time > 0s) { - this->actual_fps = 1.0 / duration_cast<seconds>(this->delta_time).count(); + this->actual_fps = static_cast<unsigned>(1.0 / this->delta_time.count()); } else { this->actual_fps = 0; } diff --git a/src/crepe/manager/LoopTimerManager.h b/src/crepe/manager/LoopTimerManager.h index 91403e4..76b02d3 100644 --- a/src/crepe/manager/LoopTimerManager.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -6,7 +6,7 @@ namespace crepe { -typedef std::chrono::duration<double> duration_t; +typedef std::chrono::duration<float> duration_t; typedef std::chrono::duration<unsigned long long, std::micro> elapsed_time_t; /** @@ -55,7 +55,7 @@ public: * * \return Current FPS. */ - unsigned get_fps() const; + unsigned int get_fps() const; /** * \brief Get the current time scale. @@ -149,9 +149,9 @@ private: private: //! Target frames per second. - unsigned target_fps = 60; + unsigned int target_fps = 60; //! Actual frames per second. - unsigned actual_fps = 0; + unsigned int actual_fps = 0; //! Time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up). float time_scale = 1; //! Maximum delta time in seconds to avoid large jumps. diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index d231c7c..680dbb8 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -13,12 +13,10 @@ using namespace std::chrono; void AISystem::update() { const Mediator & mediator = this->mediator; ComponentManager & mgr = mediator.component_manager; - LoopTimerManager & timer = mediator.loop_timer; - RefVector<AI> ai_components = mgr.get_components_by_type<AI>(); LoopTimerManager & loop_timer = mediator.loop_timer; + RefVector<AI> ai_components = mgr.get_components_by_type<AI>(); - //TODO: Use fixed loop dt (this is not available at master at the moment) - duration_t dt = loop_timer.get_delta_time(); + float dt = loop_timer.get_scaled_fixed_delta_time().count(); // Loop through all AI components for (AI & ai : ai_components) { @@ -45,7 +43,7 @@ void AISystem::update() { // Calculate the acceleration (using the above calculated force) vec2 acceleration = force / rigidbody.data.mass; // Finally, update Rigidbody's velocity - rigidbody.data.linear_velocity += acceleration * duration_cast<seconds>(dt).count(); + rigidbody.data.linear_velocity += acceleration * dt; } } @@ -146,7 +144,7 @@ vec2 AISystem::arrive(const AI & ai, const Rigidbody & rigidbody, } float speed = distance / ai.arrive_deceleration; - speed = std::min(speed, rigidbody.data.max_linear_velocity.length()); + speed = std::min(speed, rigidbody.data.max_linear_velocity); vec2 desired_velocity = to_target * (speed / distance); return desired_velocity - rigidbody.data.linear_velocity; diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index dd8c5ed..107b25d 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -3,20 +3,23 @@ #include "../api/Animator.h" #include "../manager/ComponentManager.h" #include "../manager/LoopTimerManager.h" +#include <chrono> #include "AnimatorSystem.h" using namespace crepe; +using namespace std::chrono; void AnimatorSystem::update() { ComponentManager & mgr = this->mediator.component_manager; LoopTimerManager & timer = this->mediator.loop_timer; RefVector<Animator> animations = mgr.get_components_by_type<Animator>(); - float elapsed_time = timer.get_elapsed_time().count() / 1000000.0f; + float elapsed_time = duration_cast<duration<float>>(timer.get_elapsed_time()).count(); for (Animator & a : animations) { if (!a.active) continue; + if (a.data.fps == 0) continue; Animator::Data & ctx = a.data; float frame_duration = 1.0f / ctx.fps; diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 44a0431..af8adce 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -192,13 +192,17 @@ CollisionSystem::collision_handler(CollisionInternal & data1, CollisionInternal 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 + //checks if the other velocity has a value and if this object moved + if (data1.rigidbody.data.linear_velocity.x != 0 + && 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 + //checks if the other velocity has a value and if this object moved + if (data1.rigidbody.data.linear_velocity.x != 0 + && data1.rigidbody.data.linear_velocity.y != 0) + resolution.x = -data1.rigidbody.data.linear_velocity.x * (resolution.y / data1.rigidbody.data.linear_velocity.y); } @@ -314,28 +318,48 @@ 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; - } - } - // Stop movement if bounce is disabled - else { - info.this_rigidbody.data.linear_velocity = {0, 0}; + switch (info.resolution_direction) { + case Direction::BOTH: + //bounce + if (info.this_rigidbody.data.elastisity_coefficient > 0) { + info.this_rigidbody.data.linear_velocity + = -info.this_rigidbody.data.linear_velocity + * info.this_rigidbody.data.elastisity_coefficient; + } + //stop movement + else { + info.this_rigidbody.data.linear_velocity = {0, 0}; + } + break; + case Direction::Y_DIRECTION: + // Bounce + if (info.this_rigidbody.data.elastisity_coefficient > 0) { + info.this_rigidbody.data.linear_velocity.y + = -info.this_rigidbody.data.linear_velocity.y + * info.this_rigidbody.data.elastisity_coefficient; + } + // Stop movement + else { + info.this_rigidbody.data.linear_velocity.y = 0; + info.this_transform.position.x -= info.resolution.x; + } + break; + case Direction::X_DIRECTION: + // Bounce + if (info.this_rigidbody.data.elastisity_coefficient > 0) { + info.this_rigidbody.data.linear_velocity.x + = -info.this_rigidbody.data.linear_velocity.x + * info.this_rigidbody.data.elastisity_coefficient; + } + // Stop movement + else { + info.this_rigidbody.data.linear_velocity.x = 0; + info.this_transform.position.y -= info.resolution.y; + } + break; + case Direction::NONE: + // Not possible + break; } } diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index ebf4439..3b3b8ab 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -5,88 +5,95 @@ #include "../api/Transform.h" #include "../api/Vector2.h" #include "../manager/ComponentManager.h" +#include "../manager/LoopTimerManager.h" +#include "../manager/Mediator.h" #include "PhysicsSystem.h" using namespace crepe; void PhysicsSystem::update() { - ComponentManager & mgr = this->mediator.component_manager; + + const Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; + LoopTimerManager & loop_timer = mediator.loop_timer; RefVector<Rigidbody> rigidbodies = mgr.get_components_by_type<Rigidbody>(); - RefVector<Transform> transforms = mgr.get_components_by_type<Transform>(); + float dt = loop_timer.get_scaled_fixed_delta_time().count(); - double gravity = Config::get_instance().physics.gravity; + float gravity = Config::get_instance().physics.gravity; for (Rigidbody & rigidbody : rigidbodies) { if (!rigidbody.active) continue; + Transform & transform + = mgr.get_components_by_id<Transform>(rigidbody.game_object_id).front().get(); switch (rigidbody.data.body_type) { case Rigidbody::BodyType::DYNAMIC: - for (Transform & transform : transforms) { - if (transform.game_object_id == rigidbody.game_object_id) { + if (transform.game_object_id == rigidbody.game_object_id) { + // Add gravity - // Add 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_velocity_coefficient > 0) { - 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.mass <= 0) { + throw std::runtime_error("Mass must be greater than 0"); + } - // Max velocity check - if (rigidbody.data.angular_velocity - > rigidbody.data.max_angular_velocity) { - rigidbody.data.angular_velocity - = rigidbody.data.max_angular_velocity; - } else if (rigidbody.data.angular_velocity - < -rigidbody.data.max_angular_velocity) { - rigidbody.data.angular_velocity - = -rigidbody.data.max_angular_velocity; - } + if (gravity <= 0) { + throw std::runtime_error("Config Gravity must be greater than 0"); + } - if (rigidbody.data.linear_velocity.x - > rigidbody.data.max_linear_velocity.x) { - rigidbody.data.linear_velocity.x - = rigidbody.data.max_linear_velocity.x; - } else if (rigidbody.data.linear_velocity.x - < -rigidbody.data.max_linear_velocity.x) { - rigidbody.data.linear_velocity.x - = -rigidbody.data.max_linear_velocity.x; - } + if (rigidbody.data.gravity_scale > 0 && !rigidbody.data.constraints.y) { + rigidbody.data.linear_velocity.y + += (rigidbody.data.mass * rigidbody.data.gravity_scale * gravity + * dt); + } + // Add coefficient rotation + if (rigidbody.data.angular_velocity_coefficient > 0) { + rigidbody.data.angular_velocity + *= std::pow(rigidbody.data.angular_velocity_coefficient, dt); + } - if (rigidbody.data.linear_velocity.y - > rigidbody.data.max_linear_velocity.y) { - rigidbody.data.linear_velocity.y - = rigidbody.data.max_linear_velocity.y; - } else if (rigidbody.data.linear_velocity.y - < -rigidbody.data.max_linear_velocity.y) { - rigidbody.data.linear_velocity.y - = -rigidbody.data.max_linear_velocity.y; - } + // Add coefficient movement horizontal + if (rigidbody.data.linear_velocity_coefficient.x > 0 + && !rigidbody.data.constraints.x) { + rigidbody.data.linear_velocity.x + *= std::pow(rigidbody.data.linear_velocity_coefficient.x, dt); + } - // Move object - if (!rigidbody.data.constraints.rotation) { - transform.rotation += rigidbody.data.angular_velocity; - transform.rotation = std::fmod(transform.rotation, 360.0); - if (transform.rotation < 0) { - transform.rotation += 360.0; - } - } - if (!rigidbody.data.constraints.x) { - transform.position.x += rigidbody.data.linear_velocity.x; - } - if (!rigidbody.data.constraints.y) { - transform.position.y += rigidbody.data.linear_velocity.y; + // Add coefficient movement horizontal + if (rigidbody.data.linear_velocity_coefficient.y > 0 + && !rigidbody.data.constraints.y) { + rigidbody.data.linear_velocity.y + *= std::pow(rigidbody.data.linear_velocity_coefficient.y, dt); + } + + // Max velocity check + if (rigidbody.data.angular_velocity + > rigidbody.data.max_angular_velocity) { + rigidbody.data.angular_velocity = rigidbody.data.max_angular_velocity; + } else if (rigidbody.data.angular_velocity + < -rigidbody.data.max_angular_velocity) { + rigidbody.data.angular_velocity = -rigidbody.data.max_angular_velocity; + } + + // Set max velocity to maximum length + if (rigidbody.data.linear_velocity.length() + > rigidbody.data.max_linear_velocity) { + rigidbody.data.linear_velocity.normalize(); + rigidbody.data.linear_velocity *= rigidbody.data.max_linear_velocity; + } + + // Move object + if (!rigidbody.data.constraints.rotation) { + transform.rotation += rigidbody.data.angular_velocity * dt; + transform.rotation = std::fmod(transform.rotation, 360.0); + if (transform.rotation < 0) { + transform.rotation += 360.0; } } + if (!rigidbody.data.constraints.x) { + transform.position.x += rigidbody.data.linear_velocity.x * dt; + } + if (!rigidbody.data.constraints.y) { + transform.position.y += rigidbody.data.linear_velocity.y * dt; + } } break; case Rigidbody::BodyType::KINEMATIC: diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index f4efc9f..93ba500 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -8,7 +8,6 @@ #include <crepe/api/Scene.h> #include <crepe/api/Script.h> #include <crepe/api/Sprite.h> -#include <crepe/api/Texture.h> #include <crepe/manager/Mediator.h> #include <crepe/types.h> @@ -47,14 +46,19 @@ public: GameObject game_object1 = mgr.new_object("", "", vec2{0, 0}, 0, 1); GameObject game_object2 = mgr.new_object("", "", vec2{0, 0}, 0, 1); - Texture img = Texture("asset/texture/test_ap43.png"); - game_object1.add_component<Sprite>(img, Sprite::Data{ - .color = Color::MAGENTA, - .flip = Sprite::FlipSettings{false, false}, - .sorting_in_layer = 1, - .order_in_layer = 1, - .size = {0, 195}, - }); + Asset img{"asset/texture/test_ap43.png"}; + + Sprite & test_sprite = game_object1.add_component<Sprite>( + img, Sprite::Data{ + .color = Color::MAGENTA, + .flip = Sprite::FlipSettings{false, false}, + .sorting_in_layer = 2, + .order_in_layer = 2, + .size = {0, 100}, + .angle_offset = 0, + .position_offset = {0, 0}, + }); + AI & ai = game_object1.add_component<AI>(3000); // ai.arrive_on(); // ai.flee_on(); @@ -63,7 +67,7 @@ public: ai.make_oval_path(1000, 500, {0, 500}, 4.7124, false); game_object1.add_component<Rigidbody>(Rigidbody::Data{ .mass = 0.1f, - .max_linear_velocity = {40, 40}, + .max_linear_velocity = 40, }); game_object1.add_component<BehaviorScript>().set_script<Script1>(); diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index 5dbc670..2ad65fa 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -232,7 +232,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) { collision_happend = true; 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.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; @@ -240,7 +240,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) { 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.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; @@ -260,7 +260,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction) { script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; EXPECT_EQ(ev.info.this_collider.game_object_id, 1); - EXPECT_EQ(ev.info.resolution.x, -5); + 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); @@ -268,7 +268,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_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.x, -5); EXPECT_EQ(ev.info.resolution.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); @@ -312,7 +312,7 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) { collision_happend = true; 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.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; @@ -336,7 +336,7 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) { script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; EXPECT_EQ(ev.info.this_collider.game_object_id, 1); - EXPECT_EQ(ev.info.resolution.x, -5); + 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); diff --git a/src/test/LoopTimerTest.cpp b/src/test/LoopTimerTest.cpp index d76bf45..7bd6305 100644 --- a/src/test/LoopTimerTest.cpp +++ b/src/test/LoopTimerTest.cpp @@ -30,7 +30,7 @@ TEST_F(LoopTimerTest, EnforcesTargetFrameRate) { auto elapsed_ms = duration_cast<milliseconds>(elapsed_time).count(); // For 60 FPS, the target frame time is around 16.67ms - ASSERT_NEAR(elapsed_ms, 16.7, 1); + ASSERT_NEAR(elapsed_ms, 16.7, 5); } TEST_F(LoopTimerTest, SetTargetFps) { @@ -79,3 +79,19 @@ TEST_F(LoopTimerTest, DISABLED_getCurrentTime) { ASSERT_NEAR(loop_timer.get_elapsed_time().count(), elapsed_time, 5); } +TEST_F(LoopTimerTest, getFPS) { + // Set the target FPS to 60 (which gives a target time per frame of ~16.67 ms) + loop_timer.set_target_framerate(60); + + auto start_time = steady_clock::now(); + loop_timer.enforce_frame_rate(); + + auto elapsed_time = steady_clock::now() - start_time; + loop_timer.update(); + unsigned int fps = loop_timer.get_fps(); + auto elapsed_ms = duration_cast<milliseconds>(elapsed_time).count(); + + // For 60 FPS, the target frame time is around 16.67ms + ASSERT_NEAR(elapsed_ms, 16.7, 1); + ASSERT_NEAR(fps, 60, 2); +} diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 43d2931..3afb3c7 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -3,6 +3,8 @@ #include <crepe/api/Rigidbody.h> #include <crepe/api/Transform.h> #include <crepe/manager/ComponentManager.h> +#include <crepe/manager/LoopTimerManager.h> +#include <crepe/manager/Mediator.h> #include <crepe/system/PhysicsSystem.h> #include <gtest/gtest.h> @@ -16,6 +18,7 @@ class PhysicsTest : public ::testing::Test { public: ComponentManager component_manager{m}; PhysicsSystem system{m}; + LoopTimerManager loop_timer{m}; void SetUp() override { ComponentManager & mgr = this->component_manager; @@ -27,7 +30,7 @@ public: .mass = 1, .gravity_scale = 1, .body_type = Rigidbody::BodyType::DYNAMIC, - .max_linear_velocity = vec2{10, 10}, + .max_linear_velocity = 10, .max_angular_velocity = 10, .constraints = {0, 0}, }); @@ -55,39 +58,40 @@ TEST_F(PhysicsTest, gravity) { EXPECT_EQ(transform.position.y, 0); system.update(); - EXPECT_EQ(transform.position.y, 1); + EXPECT_NEAR(transform.position.y, 0.0004, 0.0001); system.update(); - EXPECT_EQ(transform.position.y, 3); + EXPECT_NEAR(transform.position.y, 0.002, 0.001); } TEST_F(PhysicsTest, max_velocity) { ComponentManager & mgr = this->component_manager; vector<reference_wrapper<Rigidbody>> rigidbodies = mgr.get_components_by_id<Rigidbody>(0); Rigidbody & rigidbody = rigidbodies.front().get(); + rigidbody.data.gravity_scale = 0; ASSERT_FALSE(rigidbodies.empty()); EXPECT_EQ(rigidbody.data.linear_velocity.y, 0); rigidbody.add_force_linear({100, 100}); rigidbody.add_force_angular(100); system.update(); - EXPECT_EQ(rigidbody.data.linear_velocity.y, 10); - EXPECT_EQ(rigidbody.data.linear_velocity.x, 10); + EXPECT_NEAR(rigidbody.data.linear_velocity.y, 7.07, 0.01); + EXPECT_NEAR(rigidbody.data.linear_velocity.x, 7.07, 0.01); EXPECT_EQ(rigidbody.data.angular_velocity, 10); rigidbody.add_force_linear({-100, -100}); rigidbody.add_force_angular(-100); system.update(); - EXPECT_EQ(rigidbody.data.linear_velocity.y, -10); - EXPECT_EQ(rigidbody.data.linear_velocity.x, -10); + EXPECT_NEAR(rigidbody.data.linear_velocity.y, -7.07, 0.01); + EXPECT_NEAR(rigidbody.data.linear_velocity.x, -7.07, 0.01); EXPECT_EQ(rigidbody.data.angular_velocity, -10); } TEST_F(PhysicsTest, movement) { - Config::get_instance().physics.gravity = 0; ComponentManager & mgr = this->component_manager; vector<reference_wrapper<Rigidbody>> rigidbodies = mgr.get_components_by_id<Rigidbody>(0); Rigidbody & rigidbody = rigidbodies.front().get(); + rigidbody.data.gravity_scale = 0; vector<reference_wrapper<Transform>> transforms = mgr.get_components_by_id<Transform>(0); const Transform & transform = transforms.front().get(); ASSERT_FALSE(rigidbodies.empty()); @@ -96,31 +100,33 @@ TEST_F(PhysicsTest, movement) { rigidbody.add_force_linear({1, 1}); rigidbody.add_force_angular(1); system.update(); - EXPECT_EQ(transform.position.x, 1); - EXPECT_EQ(transform.position.y, 1); - EXPECT_EQ(transform.rotation, 1); + EXPECT_NEAR(transform.position.x, 0.02, 0.001); + EXPECT_NEAR(transform.position.y, 0.02, 0.001); + EXPECT_NEAR(transform.rotation, 0.02, 0.001); rigidbody.data.constraints = {1, 1, 1}; - EXPECT_EQ(transform.position.x, 1); - EXPECT_EQ(transform.position.y, 1); - EXPECT_EQ(transform.rotation, 1); - + EXPECT_NEAR(transform.position.x, 0.02, 0.001); + EXPECT_NEAR(transform.position.y, 0.02, 0.001); + EXPECT_NEAR(transform.rotation, 0.02, 0.001); + rigidbody.data.constraints = {0, 0, 0}; 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); + EXPECT_NEAR(rigidbody.data.linear_velocity.x, 0.98, 0.01); + EXPECT_NEAR(rigidbody.data.linear_velocity.y, 0.98, 0.01); + EXPECT_NEAR(rigidbody.data.angular_velocity, 0.98, 0.01); rigidbody.data.constraints = {1, 1, 0}; rigidbody.data.angular_velocity_coefficient = 0; rigidbody.data.max_angular_velocity = 1000; rigidbody.data.angular_velocity = 360; system.update(); - EXPECT_EQ(transform.rotation, 1); + EXPECT_NEAR(transform.rotation, 7.24, 0.01); rigidbody.data.angular_velocity = -360; system.update(); - EXPECT_EQ(transform.rotation, 1); + EXPECT_NEAR(transform.rotation, 0.04, 0.001); + system.update(); + EXPECT_NEAR(transform.rotation, 352.84, 0.01); } diff --git a/src/test/SceneManagerTest.cpp b/src/test/SceneManagerTest.cpp index 9bb260c..480e07a 100644 --- a/src/test/SceneManagerTest.cpp +++ b/src/test/SceneManagerTest.cpp @@ -15,11 +15,9 @@ using namespace crepe; class ConcreteScene1 : public Scene { public: void load_scene() { - Mediator & mediator = this->mediator; - ComponentManager & mgr = mediator.component_manager; - GameObject object1 = mgr.new_object("scene_1", "tag_scene_1", vec2{0, 0}, 0, 1); - GameObject object2 = mgr.new_object("scene_1", "tag_scene_1", vec2{1, 0}, 0, 1); - GameObject object3 = mgr.new_object("scene_1", "tag_scene_1", vec2{2, 0}, 0, 1); + GameObject object1 = new_object("scene_1", "tag_scene_1", vec2{0, 0}, 0, 1); + GameObject object2 = new_object("scene_1", "tag_scene_1", vec2{1, 0}, 0, 1); + GameObject object3 = new_object("scene_1", "tag_scene_1", vec2{2, 0}, 0, 1); } string get_name() const { return "scene1"; } @@ -28,12 +26,10 @@ public: class ConcreteScene2 : public Scene { public: void load_scene() { - Mediator & mediator = this->mediator; - ComponentManager & mgr = mediator.component_manager; - GameObject object1 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 0}, 0, 1); - GameObject object2 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 1}, 0, 1); - GameObject object3 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 2}, 0, 1); - GameObject object4 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 3}, 0, 1); + GameObject object1 = new_object("scene_2", "tag_scene_2", vec2{0, 0}, 0, 1); + GameObject object2 = new_object("scene_2", "tag_scene_2", vec2{0, 1}, 0, 1); + GameObject object3 = new_object("scene_2", "tag_scene_2", vec2{0, 2}, 0, 1); + GameObject object4 = new_object("scene_2", "tag_scene_2", vec2{0, 3}, 0, 1); } string get_name() const { return "scene2"; } @@ -44,9 +40,7 @@ public: ConcreteScene3(const string & name) : name(name) {} void load_scene() { - Mediator & mediator = this->mediator; - ComponentManager & mgr = mediator.component_manager; - GameObject object1 = mgr.new_object("scene_3", "tag_scene_3", vec2{0, 0}, 0, 1); + GameObject object1 = new_object("scene_3", "tag_scene_3", vec2{0, 0}, 0, 1); } string get_name() const { return name; } |