From 16444f19ae2c7c71a2be53ce6fd2e4d671aa8765 Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 4 Dec 2024 12:15:05 +0100 Subject: Modified test and setup of AISystem --- src/crepe/api/LoopManager.cpp | 14 +++++++++++++- src/crepe/system/AISystem.cpp | 6 ++++++ src/crepe/system/AISystem.h | 14 ++++++++++++++ src/crepe/system/CMakeLists.txt | 2 ++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/crepe/system/AISystem.cpp create mode 100644 src/crepe/system/AISystem.h (limited to 'src/crepe') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 7edf4d1..cd602d8 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,5 +1,6 @@ #include "../facade/SDLContext.h" +#include "../system/AISystem.h" #include "../system/AnimatorSystem.h" #include "../system/CollisionSystem.h" #include "../system/ParticleSystem.h" @@ -20,6 +21,7 @@ LoopManager::LoopManager() { this->load_system(); this->load_system(); this->load_system(); + this->load_system(); } void LoopManager::process_input() { @@ -51,6 +53,11 @@ void LoopManager::loop() { this->render(); timer.enforce_frame_rate(); + + // Stop the game after 5 seconds, for testing purposes + if (timer.get_current_time() > 5) { + this->game_running = false; + } } } @@ -58,6 +65,7 @@ void LoopManager::setup() { this->game_running = true; LoopTimer::get_instance().start(); LoopTimer::get_instance().set_fps(200); + this->scene_manager.load_next_scene(); } void LoopManager::render() { @@ -66,4 +74,8 @@ void LoopManager::render() { } } -void LoopManager::update() { LoopTimer & timer = LoopTimer::get_instance(); } +void LoopManager::update() { + LoopTimer & timer = LoopTimer::get_instance(); + this->get_system().update(); + this->get_system().update(); +} diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp new file mode 100644 index 0000000..012f4fa --- /dev/null +++ b/src/crepe/system/AISystem.cpp @@ -0,0 +1,6 @@ +#include "AISystem.h" +#include + +using namespace crepe; + +void AISystem::update() { std::cout << "AI System update" << std::endl; } diff --git a/src/crepe/system/AISystem.h b/src/crepe/system/AISystem.h new file mode 100644 index 0000000..4138e01 --- /dev/null +++ b/src/crepe/system/AISystem.h @@ -0,0 +1,14 @@ +#pragma once + +#include "System.h" + +namespace crepe { + +class AISystem : public System { +public: + using System::System; + + void update() override; +}; + +} // namespace crepe diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt index d658b25..ca89d4d 100644 --- a/src/crepe/system/CMakeLists.txt +++ b/src/crepe/system/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources(crepe PUBLIC CollisionSystem.cpp RenderSystem.cpp AnimatorSystem.cpp + AISystem.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -15,4 +16,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES CollisionSystem.h RenderSystem.h AnimatorSystem.h + AISystem.h ) -- cgit v1.2.3 From ac87bfad20e1bcf1fd066a4eda231608fe12f504 Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 4 Dec 2024 13:17:08 +0100 Subject: Added AI component --- src/crepe/api/AI.cpp | 11 +++++++++++ src/crepe/api/AI.h | 18 ++++++++++++++++++ src/crepe/api/CMakeLists.txt | 2 ++ src/example/AITest.cpp | 3 ++- 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/crepe/api/AI.cpp create mode 100644 src/crepe/api/AI.h (limited to 'src/crepe') diff --git a/src/crepe/api/AI.cpp b/src/crepe/api/AI.cpp new file mode 100644 index 0000000..6b63216 --- /dev/null +++ b/src/crepe/api/AI.cpp @@ -0,0 +1,11 @@ +#include "AI.h" + +namespace crepe { + +AI::AI(game_object_id_t id, double mass, double max_speed, double max_force) + : Component(id), + mass(mass), + max_speed(max_speed), + max_force(max_force) {} + +} // namespace crepe diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h new file mode 100644 index 0000000..b755439 --- /dev/null +++ b/src/crepe/api/AI.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Component.h" +#include "types.h" + +namespace crepe { + +class AI : public Component { +public: + AI(game_object_id_t id, double mass, double max_speed, double max_force); + +public: + double mass; + double max_speed; + double max_force; +}; + +} // namespace crepe diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 50c51ed..d42b459 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -23,6 +23,7 @@ target_sources(crepe PUBLIC Asset.cpp EventHandler.cpp Script.cpp + AI.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -58,4 +59,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES LoopManager.h LoopTimer.h Asset.h + AI.h ) diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 3998ff4..1c4633f 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -8,7 +9,6 @@ #include #include #include -#include using namespace crepe; using namespace std; @@ -24,6 +24,7 @@ public: Texture img = Texture("asset/texture/test_ap43.png"); game_object1.add_component(img, Color::MAGENTA, Sprite::FlipSettings{false, false}, 1, 1, 195); + game_object1.add_component(1, 1, 1); game_object2.add_component(Color::WHITE, ivec2{1080, 720}, vec2{1036, 780}, 1.0f); -- cgit v1.2.3 From f9f5600b60d6944dc9a7dd502988703d59d0cd62 Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 4 Dec 2024 13:46:41 +0100 Subject: Setup some behaviors --- src/crepe/api/AI.cpp | 2 +- src/crepe/api/AI.h | 47 +++++++++++++++++++++++++++++++++++++++---- src/crepe/system/AISystem.cpp | 32 +++++++++++++++++++++++++++-- src/crepe/system/AISystem.h | 6 ++++++ 4 files changed, 80 insertions(+), 7 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/AI.cpp b/src/crepe/api/AI.cpp index 6b63216..7f820a8 100644 --- a/src/crepe/api/AI.cpp +++ b/src/crepe/api/AI.cpp @@ -2,7 +2,7 @@ namespace crepe { -AI::AI(game_object_id_t id, double mass, double max_speed, double max_force) +AI::AI(game_object_id_t id, float mass, float max_speed, float max_force) : Component(id), mass(mass), max_speed(max_speed), diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h index b755439..faeeba5 100644 --- a/src/crepe/api/AI.h +++ b/src/crepe/api/AI.h @@ -7,12 +7,51 @@ namespace crepe { class AI : public Component { public: - AI(game_object_id_t id, double mass, double max_speed, double max_force); + enum BehaviorType { + NONE = 0x00000, + SEEK = 0x00002, + FLEE = 0x00004, + ARRIVE = 0x00008, + PATH_FOLLOW = 0x00010, + }; public: - double mass; - double max_speed; - double max_force; + AI(game_object_id_t id, float mass, float max_speed, float max_force); + + bool on(BehaviorType behavior) const { return (flags & behavior) == behavior; } + void seek_on() { flags |= SEEK; } + void seek_off() { + if (on(SEEK)) flags ^= SEEK; + } + void flee_on() { flags |= FLEE; } + void flee_off() { + if (on(FLEE)) flags ^= FLEE; + } + void arrive_on() { flags |= ARRIVE; } + void arrive_off() { + if (on(ARRIVE)) flags ^= ARRIVE; + } + void path_follow_on() { flags |= PATH_FOLLOW; } + void path_follow_off() { + if (on(PATH_FOLLOW)) flags ^= PATH_FOLLOW; + } + +public: + float mass; + float max_speed; + float max_force; + + // The target to seek or arrive at + vec2 seek_target; + // The target to flee from + vec2 flee_target; + // The distance at which the entity will start to flee from the target + float square_flee_panic_distance = 100.0f * 100.0f; + // The deceleration rate for the arrive behavior (higher values will make the entity decelerate faster (less overshoot)) + float arrive_deceleration = 2.0f; + +private: + int flags = 0; }; } // namespace crepe diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index 012f4fa..12da3d9 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -1,6 +1,34 @@ +#include "../ComponentManager.h" + #include "AISystem.h" -#include using namespace crepe; -void AISystem::update() { std::cout << "AI System update" << std::endl; } +void AISystem::update() { + ComponentManager & mgr = this->component_manager; + RefVector ai_components = mgr.get_components_by_type(); + + for (AI & ai : ai_components) { + vec2 force = this->calculate(ai); + //... + } +} + +vec2 AISystem::calculate(AI & ai) { + vec2 force; + + if (ai.on(AI::BehaviorType::SEEK)) { + // Seek the target + } + if (ai.on(AI::BehaviorType::FLEE)) { + // Flee from the target + } + if (ai.on(AI::BehaviorType::ARRIVE)) { + // Arrive at the target + } + if (ai.on(AI::BehaviorType::PATH_FOLLOW)) { + // Follow the path + } + + return force; +} diff --git a/src/crepe/system/AISystem.h b/src/crepe/system/AISystem.h index 4138e01..eb8d08c 100644 --- a/src/crepe/system/AISystem.h +++ b/src/crepe/system/AISystem.h @@ -1,6 +1,9 @@ #pragma once +#include "api/AI.h" + #include "System.h" +#include "types.h" namespace crepe { @@ -9,6 +12,9 @@ public: using System::System; void update() override; + +private: + vec2 calculate(AI & ai); }; } // namespace crepe -- cgit v1.2.3 From 94d95cb13e76d6cd3ec892a7f0b2bab938a9ba6a Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 4 Dec 2024 16:50:23 +0100 Subject: Extended Vector2 --- src/crepe/api/Vector2.h | 24 ++++++++ src/crepe/api/Vector2.hpp | 48 +++++++++++++++ src/test/Vector2Test.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) (limited to 'src/crepe') diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h index c278c87..bbcb932 100644 --- a/src/crepe/api/Vector2.h +++ b/src/crepe/api/Vector2.h @@ -66,6 +66,30 @@ struct Vector2 { //! Checks if this vector is not equal to another vector. bool operator!=(const Vector2 & other) const; + + //! Truncates the vector to a maximum length. + void truncate(T max); + + //! Normalizes the vector. + void normalize(); + + //! Returns the length of the vector. + T length() const; + + //! Returns the squared length of the vector. + T length_squared() const; + + //! Returns the dot product of this vector and another vector. + T dot(const Vector2 & other) const; + + //! Returns the distance between this vector and another vector. + T distance(const Vector2 & other) const; + + //! Returns the squared distance between this vector and another vector. + T distance_squared(const Vector2 & other) const; + + //! Returns the perpendicular vector to this vector. + Vector2 perpendicular() const; }; } // namespace crepe diff --git a/src/crepe/api/Vector2.hpp b/src/crepe/api/Vector2.hpp index cad15f8..ff53cb0 100644 --- a/src/crepe/api/Vector2.hpp +++ b/src/crepe/api/Vector2.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "Vector2.h" namespace crepe { @@ -115,4 +117,50 @@ bool Vector2::operator!=(const Vector2 & other) const { return !(*this == other); } +template +void Vector2::truncate(T max) { + if (length() > max) { + normalize(); + *this *= max; + } +} + +template +void Vector2::normalize() { + T len = length(); + if (len > 0) { + *this /= len; + } +} + +template +T Vector2::length() const { + return std::sqrt(x * x + y * y); +} + +template +T Vector2::length_squared() const { + return x * x + y * y; +} + +template +T Vector2::dot(const Vector2 & other) const { + return x * other.x + y * other.y; +} + +template +T Vector2::distance(const Vector2 & other) const { + return (*this - other).length(); +} + +template +T Vector2::distance_squared(const Vector2 & other) const { + return (*this - other).length_squared(); +} + +template +Vector2 Vector2::perpendicular() const { + return {-y, x}; +} + } // namespace crepe diff --git a/src/test/Vector2Test.cpp b/src/test/Vector2Test.cpp index 17bca41..1e21af9 100644 --- a/src/test/Vector2Test.cpp +++ b/src/test/Vector2Test.cpp @@ -382,3 +382,151 @@ TEST_F(Vector2Test, NotEquals) { EXPECT_FALSE(long_vec1 != long_vec1); EXPECT_TRUE(long_vec1 != long_vec2); } + +TEST_F(Vector2Test, Truncate) { + Vector2 vec = {3, 4}; + vec.truncate(3); + EXPECT_EQ(vec.x, 0); + EXPECT_EQ(vec.y, 0); + + Vector2 vec2 = {3.0, 4.0}; + vec2.truncate(3.0); + EXPECT_FLOAT_EQ(vec2.x, 1.8); + EXPECT_FLOAT_EQ(vec2.y, 2.4); + + Vector2 vec3 = {3, 4}; + vec3.truncate(3); + EXPECT_EQ(vec3.x, 0); + EXPECT_EQ(vec3.y, 0); + + Vector2 vec4 = {3.0f, 4.0f}; + vec4.truncate(3.0f); + EXPECT_FLOAT_EQ(vec4.x, 1.8f); + EXPECT_FLOAT_EQ(vec4.y, 2.4f); +} + +TEST_F(Vector2Test, Normalize) { + Vector2 vec = {3, 4}; + vec.normalize(); + EXPECT_EQ(vec.x, 0); + EXPECT_EQ(vec.y, 0); + + Vector2 vec2 = {3.0, 4.0}; + vec2.normalize(); + EXPECT_FLOAT_EQ(vec2.x, 0.6); + EXPECT_FLOAT_EQ(vec2.y, 0.8); + + Vector2 vec3 = {3, 4}; + vec3.normalize(); + EXPECT_EQ(vec3.x, 0); + EXPECT_EQ(vec3.y, 0); + + Vector2 vec4 = {3.0f, 4.0f}; + vec4.normalize(); + EXPECT_FLOAT_EQ(vec4.x, 0.6f); + EXPECT_FLOAT_EQ(vec4.y, 0.8f); +} + +TEST_F(Vector2Test, Length) { + Vector2 vec = {3, 4}; + EXPECT_EQ(vec.length(), 5); + + Vector2 vec2 = {3.0, 4.0}; + EXPECT_FLOAT_EQ(vec2.length(), 5.0); + + Vector2 vec3 = {3, 4}; + EXPECT_EQ(vec3.length(), 5); + + Vector2 vec4 = {3.0f, 4.0f}; + EXPECT_FLOAT_EQ(vec4.length(), 5.0f); +} + +TEST_F(Vector2Test, LengthSquared) { + Vector2 vec = {3, 4}; + EXPECT_EQ(vec.length_squared(), 25); + + Vector2 vec2 = {3.0, 4.0}; + EXPECT_FLOAT_EQ(vec2.length_squared(), 25.0); + + Vector2 vec3 = {3, 4}; + EXPECT_EQ(vec3.length_squared(), 25); + + Vector2 vec4 = {3.0f, 4.0f}; + EXPECT_FLOAT_EQ(vec4.length_squared(), 25.0f); +} + +TEST_F(Vector2Test, Dot) { + Vector2 vec1 = {3, 4}; + Vector2 vec2 = {5, 6}; + EXPECT_EQ(vec1.dot(vec2), 39); + + Vector2 vec3 = {3.0, 4.0}; + Vector2 vec4 = {5.0, 6.0}; + EXPECT_FLOAT_EQ(vec3.dot(vec4), 39.0); + + Vector2 vec5 = {3, 4}; + Vector2 vec6 = {5, 6}; + EXPECT_EQ(vec5.dot(vec6), 39); + + Vector2 vec7 = {3.0f, 4.0f}; + Vector2 vec8 = {5.0f, 6.0f}; + EXPECT_FLOAT_EQ(vec7.dot(vec8), 39.0f); +} + +TEST_F(Vector2Test, Distance) { + Vector2 vec1 = {1, 1}; + Vector2 vec2 = {4, 5}; + EXPECT_EQ(vec1.distance(vec2), 5); + + Vector2 vec3 = {1.0, 1.0}; + Vector2 vec4 = {4.0, 5.0}; + EXPECT_FLOAT_EQ(vec3.distance(vec4), 5.0); + + Vector2 vec5 = {1, 1}; + Vector2 vec6 = {4, 5}; + EXPECT_EQ(vec5.distance(vec6), 5); + + Vector2 vec7 = {1.0f, 1.0f}; + Vector2 vec8 = {4.0f, 5.0f}; + EXPECT_FLOAT_EQ(vec7.distance(vec8), 5.0f); +} + +TEST_F(Vector2Test, DistanceSquared) { + Vector2 vec1 = {3, 4}; + Vector2 vec2 = {5, 6}; + EXPECT_EQ(vec1.distance_squared(vec2), 8); + + Vector2 vec3 = {3.0, 4.0}; + Vector2 vec4 = {5.0, 6.0}; + EXPECT_FLOAT_EQ(vec3.distance_squared(vec4), 8.0); + + Vector2 vec5 = {3, 4}; + Vector2 vec6 = {5, 6}; + EXPECT_EQ(vec5.distance_squared(vec6), 8); + + Vector2 vec7 = {3.0f, 4.0f}; + Vector2 vec8 = {5.0f, 6.0f}; + EXPECT_FLOAT_EQ(vec7.distance_squared(vec8), 8.0f); +} + +TEST_F(Vector2Test, Perpendicular) { + Vector2 vec = {3, 4}; + Vector2 result = vec.perpendicular(); + EXPECT_EQ(result.x, -4); + EXPECT_EQ(result.y, 3); + + Vector2 vec2 = {3.0, 4.0}; + Vector2 result2 = vec2.perpendicular(); + EXPECT_FLOAT_EQ(result2.x, -4.0); + EXPECT_FLOAT_EQ(result2.y, 3.0); + + Vector2 vec3 = {3, 4}; + Vector2 result3 = vec3.perpendicular(); + EXPECT_EQ(result3.x, -4); + EXPECT_EQ(result3.y, 3); + + Vector2 vec4 = {3.0f, 4.0f}; + Vector2 result4 = vec4.perpendicular(); + EXPECT_FLOAT_EQ(result4.x, -4.0f); + EXPECT_FLOAT_EQ(result4.y, 3.0f); +} -- cgit v1.2.3 From e303bd4c54b0edbcd1819a47a5d8aaef88211a09 Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 4 Dec 2024 17:27:30 +0100 Subject: Increased gameloop time --- src/crepe/api/LoopManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index cd602d8..46831e8 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -54,8 +54,8 @@ void LoopManager::loop() { timer.enforce_frame_rate(); - // Stop the game after 5 seconds, for testing purposes - if (timer.get_current_time() > 5) { + // Stop the game after 10 seconds, for testing purposes + if (timer.get_current_time() > 10) { this->game_running = false; } } -- cgit v1.2.3 From 121387ba92a23d6f17b36331d25757abc899f7d2 Mon Sep 17 00:00:00 2001 From: max-001 Date: Wed, 4 Dec 2024 17:27:51 +0100 Subject: Implemeted seek behavior --- src/crepe/api/AI.h | 3 +++ src/crepe/system/AISystem.cpp | 45 +++++++++++++++++++++++++++++++++++++++++-- src/crepe/system/AISystem.h | 3 +++ src/example/AITest.cpp | 4 ++-- 4 files changed, 51 insertions(+), 4 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h index faeeba5..242ff89 100644 --- a/src/crepe/api/AI.h +++ b/src/crepe/api/AI.h @@ -51,6 +51,9 @@ public: float arrive_deceleration = 2.0f; private: + vec2 velocity; + friend class AISystem; + int flags = 0; }; diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index 12da3d9..9029f32 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -1,4 +1,7 @@ #include "../ComponentManager.h" +#include "api/LoopTimer.h" +#include "api/Transform.h" +#include "types.h" #include "AISystem.h" @@ -8,9 +11,19 @@ void AISystem::update() { ComponentManager & mgr = this->component_manager; RefVector ai_components = mgr.get_components_by_type(); + double dt = LoopTimer::get_instance().get_delta_time(); + for (AI & ai : ai_components) { vec2 force = this->calculate(ai); - //... + vec2 acceleration = force / ai.mass; + ai.velocity += acceleration * dt; + ai.velocity.truncate(ai.max_speed); + + // Update the position + RefVector transforms + = mgr.get_components_by_id(ai.game_object_id); + Transform & transform = transforms.front().get(); + transform.position += ai.velocity * dt; } } @@ -18,7 +31,11 @@ vec2 AISystem::calculate(AI & ai) { vec2 force; if (ai.on(AI::BehaviorType::SEEK)) { - // Seek the target + vec2 force_to_add = this->seek(ai); + + if (!this->accumulate_force(force, force_to_add)) { + return force; + } } if (ai.on(AI::BehaviorType::FLEE)) { // Flee from the target @@ -32,3 +49,27 @@ vec2 AISystem::calculate(AI & ai) { return force; } + +bool AISystem::accumulate_force(vec2 & running_total, vec2 force_to_add) { + double magnitude_remaining = running_total.length(); + double magnitude_to_add = force_to_add.length(); + + if (magnitude_remaining + magnitude_to_add > 0) { + running_total += force_to_add; + return true; + } + + return false; +} + +vec2 AISystem::seek(const AI & ai) { + ComponentManager & mgr = this->component_manager; + RefVector transforms = mgr.get_components_by_id(ai.game_object_id); + Transform & transform = transforms.front().get(); + + vec2 desired_velocity = ai.seek_target - transform.position; + desired_velocity.normalize(); + desired_velocity *= ai.max_speed; + + return desired_velocity - ai.velocity; +} diff --git a/src/crepe/system/AISystem.h b/src/crepe/system/AISystem.h index eb8d08c..5e94ccb 100644 --- a/src/crepe/system/AISystem.h +++ b/src/crepe/system/AISystem.h @@ -15,6 +15,9 @@ public: private: vec2 calculate(AI & ai); + bool accumulate_force(vec2 & running_total, vec2 force_to_add); + + vec2 seek(const AI & ai); }; } // namespace crepe diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 1c4633f..341e1de 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -18,13 +18,13 @@ public: void load_scene() override { ComponentManager & mgr = this->component_manager; - GameObject game_object1 = mgr.new_object("", "", vec2{0, 0}, 0, 1); + GameObject game_object1 = mgr.new_object("", "", vec2{250, 250}, 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(img, Color::MAGENTA, Sprite::FlipSettings{false, false}, 1, 1, 195); - game_object1.add_component(1, 1, 1); + game_object1.add_component(1, 200, 200).seek_on(); game_object2.add_component(Color::WHITE, ivec2{1080, 720}, vec2{1036, 780}, 1.0f); -- cgit v1.2.3 From e617b4f002638e37dbe4d2ce13849728e7e82c78 Mon Sep 17 00:00:00 2001 From: max-001 Date: Thu, 5 Dec 2024 17:26:41 +0100 Subject: Used Mediator --- src/crepe/system/AISystem.cpp | 9 ++++++--- src/example/AITest.cpp | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index 9029f32..c67d5ea 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -1,6 +1,7 @@ -#include "../ComponentManager.h" +#include "manager/ComponentManager.h" #include "api/LoopTimer.h" #include "api/Transform.h" +#include "manager/Mediator.h" #include "types.h" #include "AISystem.h" @@ -8,7 +9,8 @@ using namespace crepe; void AISystem::update() { - ComponentManager & mgr = this->component_manager; + const Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; RefVector ai_components = mgr.get_components_by_type(); double dt = LoopTimer::get_instance().get_delta_time(); @@ -63,7 +65,8 @@ bool AISystem::accumulate_force(vec2 & running_total, vec2 force_to_add) { } vec2 AISystem::seek(const AI & ai) { - ComponentManager & mgr = this->component_manager; + const Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; RefVector transforms = mgr.get_components_by_id(ai.game_object_id); Transform & transform = transforms.front().get(); diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 341e1de..71aacb2 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -1,6 +1,7 @@ +#include #include #include -#include +#include #include #include #include @@ -16,7 +17,8 @@ using namespace std; class Scene1 : public Scene { public: void load_scene() override { - ComponentManager & mgr = this->component_manager; + Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; GameObject game_object1 = mgr.new_object("", "", vec2{250, 250}, 0, 1); GameObject game_object2 = mgr.new_object("", "", vec2{0, 0}, 0, 1); -- cgit v1.2.3 From 6b45759e570bcaafc167e74ac46c8ffe05efa66e Mon Sep 17 00:00:00 2001 From: max-001 Date: Thu, 5 Dec 2024 18:28:15 +0100 Subject: Make format --- src/crepe/system/AISystem.cpp | 2 +- src/example/AITest.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index c67d5ea..3c61c78 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -1,6 +1,6 @@ -#include "manager/ComponentManager.h" #include "api/LoopTimer.h" #include "api/Transform.h" +#include "manager/ComponentManager.h" #include "manager/Mediator.h" #include "types.h" diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 71aacb2..841b195 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -1,7 +1,5 @@ -#include #include #include -#include #include #include #include @@ -10,6 +8,8 @@ #include #include #include +#include +#include using namespace crepe; using namespace std; -- cgit v1.2.3 From 9cd9e3674d8b1c326c81b7896b9254408fb19972 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 08:42:49 +0100 Subject: Added some explanation to Vector2 --- src/crepe/api/Vector2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h index bbcb932..bf9d124 100644 --- a/src/crepe/api/Vector2.h +++ b/src/crepe/api/Vector2.h @@ -70,7 +70,7 @@ struct Vector2 { //! Truncates the vector to a maximum length. void truncate(T max); - //! Normalizes the vector. + //! Normalizes the vector (resulting in vector with a length of 1). void normalize(); //! Returns the length of the vector. @@ -79,7 +79,7 @@ struct Vector2 { //! Returns the squared length of the vector. T length_squared() const; - //! Returns the dot product of this vector and another vector. + //! Returns the dot product (inwendig product) of this vector and another vector. T dot(const Vector2 & other) const; //! Returns the distance between this vector and another vector. -- cgit v1.2.3 From cbd7663b7f9cf7bf2b498f54b5d86c2ca37a5188 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 09:56:54 +0100 Subject: Modified game loop --- src/crepe/api/LoopManager.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 2f8a0a7..90308a7 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -40,6 +40,7 @@ void LoopManager::fixed_update() { EventManager & ev = this->mediator.event_manager; ev.dispatch_events(); this->get_system().update(); + this->get_system().update(); this->get_system().update(); this->get_system().update(); } @@ -50,22 +51,17 @@ void LoopManager::loop() { while (game_running) { timer.update(); - + while (timer.get_lag() >= timer.get_fixed_delta_time()) { this->process_input(); this->fixed_update(); timer.advance_fixed_update(); } - + this->update(); this->render(); timer.enforce_frame_rate(); - - // Stop the game after 10 seconds, for testing purposes - if (timer.get_current_time() > 10) { - this->game_running = false; - } } } @@ -75,7 +71,6 @@ void LoopManager::setup() { this->scene_manager.load_next_scene(); timer.start(); timer.set_fps(200); - this->scene_manager.load_next_scene(); } void LoopManager::render() { @@ -84,7 +79,4 @@ void LoopManager::render() { this->get_system().update(); } -void LoopManager::update() { - this->get_system().update(); - this->get_system().update(); -} +void LoopManager::update() { this->get_system().update(); } -- cgit v1.2.3 From 93893dbe710d864d5865f361f9a8a8f8f85b94f6 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 09:57:30 +0100 Subject: Make format --- mwe/events/include/event.h | 2 +- src/crepe/api/Rigidbody.h | 1 - src/crepe/api/Script.h | 2 +- src/crepe/system/CollisionSystem.cpp | 40 +++++++-------- src/crepe/system/CollisionSystem.h | 6 +-- src/example/game.cpp | 98 +++++++++++++++++------------------- src/test/CollisionTest.cpp | 6 +-- src/test/Profiling.cpp | 6 +-- 8 files changed, 76 insertions(+), 85 deletions(-) (limited to 'src/crepe') diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index ee1bf52..e1b220b 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent") {}; + ShutDownEvent() : Event("ShutDownEvent"){}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index b0a24f7..722a665 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -7,7 +7,6 @@ #include "types.h" - namespace crepe { /** diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index 1474a09..fa83152 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -3,10 +3,10 @@ #include #include "../manager/EventManager.h" -#include "system/CollisionSystem.h" #include "../manager/Mediator.h" #include "../types.h" #include "../util/OptionalRef.h" +#include "system/CollisionSystem.h" namespace crepe { diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index f75d0ad..da9e3af 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -6,6 +6,8 @@ #include #include +#include "../manager/ComponentManager.h" +#include "../manager/EventManager.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" #include "api/Event.h" @@ -13,8 +15,6 @@ #include "api/Rigidbody.h" #include "api/Transform.h" #include "api/Vector2.h" -#include "../manager/ComponentManager.h" -#include "../manager/EventManager.h" #include "Collider.h" #include "CollisionSystem.h" @@ -27,17 +27,14 @@ void CollisionSystem::update() { std::vector all_colliders; game_object_id_t id = 0; ComponentManager & mgr = this->mediator.component_manager; - RefVector rigidbodies - = mgr.get_components_by_type(); + RefVector rigidbodies = mgr.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 - = mgr.get_components_by_id(id).front().get(); + Transform & transform = mgr.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 = mgr.get_components_by_type(); for (BoxCollider & boxcollider : boxcolliders) { if (boxcollider.game_object_id != id) continue; if (!boxcollider.active) continue; @@ -159,7 +156,7 @@ CollisionSystem::collision_handler(CollisionInternal & data1, CollisionInternal 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,true); + collider_pos1, true); break; } case CollisionInternalType::CIRCLE_CIRCLE: { @@ -185,7 +182,7 @@ CollisionSystem::collision_handler(CollisionInternal & data1, CollisionInternal 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,false); + collider_pos2, false); break; } } @@ -261,7 +258,6 @@ vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider & circle // Normalize the delta vector to get the collision direction vec2 collision_normal = delta / distance; - // Compute the resolution vector vec2 resolution = -collision_normal * penetration_depth; @@ -272,7 +268,8 @@ vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider & circle vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider & circle_collider, const BoxCollider & box_collider, const vec2 & circle_position, - const vec2 & box_position,bool inverse) const { + const vec2 & box_position, + bool inverse) const { vec2 delta = circle_position - box_position; // Compute half-dimensions of the box @@ -294,7 +291,7 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider & circle_co // Compute penetration depth float penetration_depth = circle_collider.radius - distance; - if(inverse) collision_normal = -collision_normal; + if (inverse) collision_normal = -collision_normal; // Compute the resolution vector vec2 resolution = collision_normal * penetration_depth; @@ -311,8 +308,7 @@ void CollisionSystem::determine_collision_handler(CollisionInfo & info) { // Call collision event for user CollisionEvent data(info); EventManager & emgr = this->mediator.event_manager; - emgr.trigger_event( - data, info.this_collider.game_object_id); + emgr.trigger_event(data, info.this_collider.game_object_id); } void CollisionSystem::static_collision_handler(CollisionInfo & info) { @@ -389,14 +385,14 @@ CollisionSystem::gather_collisions(std::vector & colliders) { bool CollisionSystem::have_common_layer(const std::set & layers1, const std::set & layers2) { - + // Check if any number is equal in the layers for (int num : layers1) { - if (layers2.contains(num)) { - // Common layer found - return true; - break; - } + if (layers2.contains(num)) { + // Common layer found + return true; + break; + } } // No common layer found return false; @@ -512,7 +508,7 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider & box1, float distance_squared = distance_x * distance_x + distance_y * distance_y; // Compare distance squared with the square of the circle's radius - return distance_squared <= circle2.radius * circle2.radius-1; + return distance_squared <= circle2.radius * circle2.radius - 1; } bool CollisionSystem::get_circle_circle_collision(const CircleCollider & circle1, diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index b978dbb..eee582b 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -6,11 +6,11 @@ #include "api/BoxCollider.h" #include "api/CircleCollider.h" +#include "api/Event.h" #include "api/Metadata.h" #include "api/Rigidbody.h" #include "api/Transform.h" #include "api/Vector2.h" -#include "api/Event.h" #include "Collider.h" #include "System.h" @@ -183,8 +183,8 @@ private: */ vec2 get_circle_box_resolution(const CircleCollider & circle_collider, const BoxCollider & box_collider, - const vec2 & circle_position, - const vec2 & box_position,bool inverse) const; + const vec2 & circle_position, const vec2 & box_position, + bool inverse) const; /** * \brief Determines the appropriate collision handler for a collision. diff --git a/src/example/game.cpp b/src/example/game.cpp index be756bd..2b4e46f 100644 --- a/src/example/game.cpp +++ b/src/example/game.cpp @@ -1,6 +1,6 @@ #include "api/CircleCollider.h" -#include "manager/ComponentManager.h" #include "api/Scene.h" +#include "manager/ComponentManager.h" #include "manager/Mediator.h" #include #include @@ -28,66 +28,64 @@ class MyScript1 : public Script { bool keypressed(const KeyPressEvent & test) { Log::logf("Box script keypressed()"); switch (test.key) { - case Keycode::A: - { + case Keycode::A: { Transform & tf = this->get_component(); tf.position.x -= 1; break; } - case Keycode::W: - { + case Keycode::W: { Transform & tf = this->get_component(); tf.position.y -= 1; break; } - case Keycode::S: - { + case Keycode::S: { Transform & tf = this->get_component(); tf.position.y += 1; break; } - case Keycode::D: - { + case Keycode::D: { Transform & tf = this->get_component(); tf.position.x += 1; break; } - case Keycode::E: - { - if(flip){ + case Keycode::E: { + if (flip) { flip = false; this->get_component().active = true; this->get_components()[0].get().active = true; this->get_component().active = false; this->get_components()[1].get().active = false; - } - else { + } else { flip = true; this->get_component().active = false; this->get_components()[0].get().active = false; this->get_component().active = true; this->get_components()[1].get().active = true; } - - + //add collider switch break; } + case Keycode::Q: { + throw "Test"; + break; + } default: - break; + break; } return false; - } + } void init() { Log::logf("init"); - subscribe([this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); }); - subscribe([this](const KeyPressEvent & ev) -> bool { return this->keypressed(ev); }); + subscribe( + [this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); }); + subscribe( + [this](const KeyPressEvent & ev) -> bool { return this->keypressed(ev); }); } void update() { // Retrieve component from the same GameObject this script is on } - }; class MyScript2 : public Script { @@ -99,74 +97,68 @@ class MyScript2 : public Script { bool keypressed(const KeyPressEvent & test) { Log::logf("Box script keypressed()"); switch (test.key) { - case Keycode::LEFT: - { + case Keycode::LEFT: { Transform & tf = this->get_component(); tf.position.x -= 1; break; } - case Keycode::UP: - { + case Keycode::UP: { Transform & tf = this->get_component(); tf.position.y -= 1; break; } - case Keycode::DOWN: - { + case Keycode::DOWN: { Transform & tf = this->get_component(); tf.position.y += 1; break; } - case Keycode::RIGHT: - { + case Keycode::RIGHT: { Transform & tf = this->get_component(); tf.position.x += 1; break; } - case Keycode::PAUSE: - { - if(flip){ + case Keycode::PAUSE: { + if (flip) { flip = false; this->get_component().active = true; this->get_components()[0].get().active = true; this->get_component().active = false; this->get_components()[1].get().active = false; - } - else { + } else { flip = true; this->get_component().active = false; this->get_components()[0].get().active = false; this->get_component().active = true; this->get_components()[1].get().active = true; } - - + //add collider switch break; } default: - break; + break; } return false; - } + } void init() { Log::logf("init"); - subscribe([this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); }); - subscribe([this](const KeyPressEvent & ev) -> bool { return this->keypressed(ev); }); + subscribe( + [this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); }); + subscribe( + [this](const KeyPressEvent & ev) -> bool { return this->keypressed(ev); }); } void update() { // Retrieve component from the same GameObject this script is on } - }; class ConcreteScene1 : public Scene { public: using Scene::Scene; - + void load_scene() { - + Mediator & m = this->mediator; ComponentManager & mgr = m.component_manager; Color color(0, 0, 0, 255); @@ -195,7 +187,10 @@ public: 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{static_cast(screen_size_width), static_cast(screen_size_height)}, vec2{screen_size_width, screen_size_height}, 1.0f); + world.add_component( + Color::WHITE, + ivec2{static_cast(screen_size_width), static_cast(screen_size_height)}, + vec2{screen_size_width, screen_size_height}, 1.0f); GameObject game_object1 = mgr.new_object( "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1); @@ -219,10 +214,10 @@ public: //add circle with cirlcecollider deactiveated game_object1.add_component(vec2{0, 0}, 10).active = false; auto img2 = Texture("asset/texture/circle.png"); - game_object1.add_component(img2, color, Sprite::FlipSettings{false, false}, 1, - 1, 20).active = false; - - + game_object1 + .add_component(img2, color, Sprite::FlipSettings{false, false}, 1, 1, 20) + .active + = false; GameObject game_object2 = mgr.new_object( "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1); @@ -246,9 +241,10 @@ public: //add circle with cirlcecollider deactiveated game_object2.add_component(vec2{0, 0}, 10).active = false; auto img4 = Texture("asset/texture/circle.png"); - game_object2.add_component(img4, color, Sprite::FlipSettings{false, false}, 1, - 1, 20).active = false; - + game_object2 + .add_component(img4, color, Sprite::FlipSettings{false, false}, 1, 1, 20) + .active + = false; } string get_name() const { return "scene1"; } diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index a683b1f..dd45eb6 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -7,14 +7,14 @@ #define private public #define protected public -#include -#include #include -#include #include #include #include #include +#include +#include +#include #include #include #include diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index 91be769..f091d9d 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -9,14 +9,14 @@ #define private public #define protected public -#include #include -#include #include #include #include #include #include +#include +#include #include #include #include @@ -162,7 +162,7 @@ TEST_F(Profiling, Profiling_2) { .body_type = Rigidbody::BodyType::STATIC, }); gameobject.add_component(vec2{0, 0}, vec2{1, 1}); - + gameobject.add_component().set_script(); Color color(0, 0, 0, 0); auto img = Texture("asset/texture/green_square.png"); -- cgit v1.2.3 From 9c2cafd85ed7aa9a860ba25fbe2bd3ccc2439f29 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 10:39:18 +0100 Subject: Using Rigidbody from now on --- src/crepe/api/AI.cpp | 6 +----- src/crepe/api/AI.h | 7 +------ src/crepe/system/AISystem.cpp | 22 +++++++++++----------- src/example/AITest.cpp | 6 +++++- 4 files changed, 18 insertions(+), 23 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/AI.cpp b/src/crepe/api/AI.cpp index 7f820a8..d785bb5 100644 --- a/src/crepe/api/AI.cpp +++ b/src/crepe/api/AI.cpp @@ -2,10 +2,6 @@ namespace crepe { -AI::AI(game_object_id_t id, float mass, float max_speed, float max_force) - : Component(id), - mass(mass), - max_speed(max_speed), - max_force(max_force) {} +AI::AI(game_object_id_t id, float max_force) : Component(id), max_force(max_force) {} } // namespace crepe diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h index 242ff89..046426d 100644 --- a/src/crepe/api/AI.h +++ b/src/crepe/api/AI.h @@ -16,7 +16,7 @@ public: }; public: - AI(game_object_id_t id, float mass, float max_speed, float max_force); + AI(game_object_id_t id, float max_force); bool on(BehaviorType behavior) const { return (flags & behavior) == behavior; } void seek_on() { flags |= SEEK; } @@ -37,8 +37,6 @@ public: } public: - float mass; - float max_speed; float max_force; // The target to seek or arrive at @@ -51,9 +49,6 @@ public: float arrive_deceleration = 2.0f; private: - vec2 velocity; - friend class AISystem; - int flags = 0; }; diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index 3c61c78..d496e12 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -1,4 +1,5 @@ #include "api/LoopTimer.h" +#include "api/Rigidbody.h" #include "api/Transform.h" #include "manager/ComponentManager.h" #include "manager/Mediator.h" @@ -16,16 +17,13 @@ void AISystem::update() { double dt = LoopTimer::get_instance().get_delta_time(); for (AI & ai : ai_components) { + RefVector rigidbodies + = mgr.get_components_by_id(ai.game_object_id); + Rigidbody & rigidbody = rigidbodies.front().get(); + vec2 force = this->calculate(ai); - vec2 acceleration = force / ai.mass; - ai.velocity += acceleration * dt; - ai.velocity.truncate(ai.max_speed); - - // Update the position - RefVector transforms - = mgr.get_components_by_id(ai.game_object_id); - Transform & transform = transforms.front().get(); - transform.position += ai.velocity * dt; + vec2 acceleration = force / rigidbody.data.mass; + rigidbody.data.linear_velocity += acceleration * dt; } } @@ -69,10 +67,12 @@ vec2 AISystem::seek(const AI & ai) { ComponentManager & mgr = mediator.component_manager; RefVector transforms = mgr.get_components_by_id(ai.game_object_id); Transform & transform = transforms.front().get(); + RefVector rigidbodies = mgr.get_components_by_id(ai.game_object_id); + Rigidbody & rigidbody = rigidbodies.front().get(); vec2 desired_velocity = ai.seek_target - transform.position; desired_velocity.normalize(); - desired_velocity *= ai.max_speed; + desired_velocity *= rigidbody.data.max_linear_velocity; - return desired_velocity - ai.velocity; + return desired_velocity - rigidbody.data.linear_velocity; } diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 91a529c..2b6a4d6 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,10 @@ public: Texture img = Texture("asset/texture/test_ap43.png"); game_object1.add_component(img, Color::MAGENTA, Sprite::FlipSettings{false, false}, 1, 1, 195); - game_object1.add_component(1, 200, 200).seek_on(); + game_object1.add_component(200).seek_on(); + game_object1.add_component(Rigidbody::Data{ + .mass = 1.0f, .max_linear_velocity = {21, 21}, // sqrt(21^2 + 21^2) = 30 + }); game_object2.add_component(Color::WHITE, ivec2{1080, 720}, vec2{1036, 780}, 1.0f); -- cgit v1.2.3 From 82863204048d65073bc5598dcb62f31e32b51430 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 10:46:16 +0100 Subject: Corrected accumulate_force() --- src/crepe/system/AISystem.cpp | 21 ++++++++++++++------- src/crepe/system/AISystem.h | 5 ++++- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index d496e12..4858000 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -33,7 +33,7 @@ vec2 AISystem::calculate(AI & ai) { if (ai.on(AI::BehaviorType::SEEK)) { vec2 force_to_add = this->seek(ai); - if (!this->accumulate_force(force, force_to_add)) { + if (!this->accumulate_force(ai, force, force_to_add)) { return force; } } @@ -50,16 +50,23 @@ vec2 AISystem::calculate(AI & ai) { return force; } -bool AISystem::accumulate_force(vec2 & running_total, vec2 force_to_add) { - double magnitude_remaining = running_total.length(); - double magnitude_to_add = force_to_add.length(); +bool AISystem::accumulate_force(AI & ai, vec2 & running_total, vec2 force_to_add) { + float magnitude = running_total.length(); + float magnitude_remaining = ai.max_force - magnitude; - if (magnitude_remaining + magnitude_to_add > 0) { + if (magnitude_remaining <= 0.0f) { + return false; + } + + float magnitude_to_add = force_to_add.length(); + if (magnitude_to_add < magnitude_remaining) { running_total += force_to_add; - return true; + } else { + force_to_add.normalize(); + running_total += force_to_add * magnitude_remaining; } - return false; + return true; } vec2 AISystem::seek(const AI & ai) { diff --git a/src/crepe/system/AISystem.h b/src/crepe/system/AISystem.h index 5e94ccb..18f1c61 100644 --- a/src/crepe/system/AISystem.h +++ b/src/crepe/system/AISystem.h @@ -15,9 +15,12 @@ public: private: vec2 calculate(AI & ai); - bool accumulate_force(vec2 & running_total, vec2 force_to_add); + bool accumulate_force(AI & ai, vec2 & running_total, vec2 force_to_add); vec2 seek(const AI & ai); + vec2 flee(const AI & ai); + vec2 arrive(const AI & ai); + vec2 path_follow(const AI & ai); }; } // namespace crepe -- cgit v1.2.3 From 9eac8d31b25c234a21b1d188df17e77e71f48088 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 16:21:40 +0100 Subject: Improved example --- src/crepe/system/CollisionSystem.cpp | 2 -- src/example/AITest.cpp | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 2a487fd..1282f7a 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -550,5 +550,3 @@ vec2 CollisionSystem::get_current_position(const vec2 & collider_offset, // Final positions considering scaling and rotation return (transform.position + vec2(rotated_total_offset_x1, rotated_total_offset_y1)); } - - diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 2b6a4d6..144aef3 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace crepe; using namespace std; @@ -23,9 +24,19 @@ class Script1 : public Script { return true; } + bool mousemove(const MouseMoveEvent & event) { + RefVector aivec = this->get_components(); + AI & ai = aivec.front().get(); + ai.seek_target + = vec2{static_cast(event.mouse_x), static_cast(event.mouse_y)}; + return true; + } + void init() { subscribe( [this](const ShutDownEvent & ev) -> bool { return this->shutdown(ev); }); + subscribe( + [this](const MouseMoveEvent & ev) -> bool { return this->mousemove(ev); }); } }; @@ -41,14 +52,14 @@ public: Texture img = Texture("asset/texture/test_ap43.png"); game_object1.add_component(img, Color::MAGENTA, Sprite::FlipSettings{false, false}, 1, 1, 195); - game_object1.add_component(200).seek_on(); + game_object1.add_component(30).seek_on(); game_object1.add_component(Rigidbody::Data{ - .mass = 1.0f, .max_linear_velocity = {21, 21}, // sqrt(21^2 + 21^2) = 30 + .mass = 0.5f, .max_linear_velocity = {21, 21}, // sqrt(21^2 + 21^2) = 30 }); + game_object1.add_component().set_script(); game_object2.add_component(Color::WHITE, ivec2{1080, 720}, vec2{1036, 780}, 1.0f); - game_object2.add_component().set_script(); } string get_name() const override { return "Scene1"; } -- cgit v1.2.3 From 0d0943d23364d7110f0232e3564f4ea63af13db2 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 16:41:51 +0100 Subject: Implemented flee and arrive behaviors --- src/crepe/api/AI.h | 4 +-- src/crepe/system/AISystem.cpp | 71 ++++++++++++++++++++++++++++++++++++++----- src/example/AITest.cpp | 6 ++-- 3 files changed, 69 insertions(+), 12 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h index 046426d..d4bd9d3 100644 --- a/src/crepe/api/AI.h +++ b/src/crepe/api/AI.h @@ -44,9 +44,9 @@ public: // The target to flee from vec2 flee_target; // The distance at which the entity will start to flee from the target - float square_flee_panic_distance = 100.0f * 100.0f; + float square_flee_panic_distance = 200.0f * 200.0f; // The deceleration rate for the arrive behavior (higher values will make the entity decelerate faster (less overshoot)) - float arrive_deceleration = 2.0f; + float arrive_deceleration = 40.0f; private: int flags = 0; diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index 4858000..ce3147f 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -1,11 +1,14 @@ +#include +#include + #include "api/LoopTimer.h" #include "api/Rigidbody.h" #include "api/Transform.h" #include "manager/ComponentManager.h" #include "manager/Mediator.h" -#include "types.h" #include "AISystem.h" +#include "types.h" using namespace crepe; @@ -30,21 +33,33 @@ void AISystem::update() { vec2 AISystem::calculate(AI & ai) { vec2 force; - if (ai.on(AI::BehaviorType::SEEK)) { - vec2 force_to_add = this->seek(ai); + if (ai.on(AI::BehaviorType::FLEE)) { + vec2 force_to_add = this->flee(ai); if (!this->accumulate_force(ai, force, force_to_add)) { return force; } } - if (ai.on(AI::BehaviorType::FLEE)) { - // Flee from the target - } if (ai.on(AI::BehaviorType::ARRIVE)) { - // Arrive at the target + vec2 force_to_add = this->arrive(ai); + + if (!this->accumulate_force(ai, force, force_to_add)) { + return force; + } + } + if (ai.on(AI::BehaviorType::SEEK)) { + vec2 force_to_add = this->seek(ai); + + if (!this->accumulate_force(ai, force, force_to_add)) { + return force; + } } if (ai.on(AI::BehaviorType::PATH_FOLLOW)) { - // Follow the path + /*vec2 force_to_add = this->path_follow(ai); + + if (!this->accumulate_force(ai, force, force_to_add)) { + return force; + }*/ } return force; @@ -83,3 +98,43 @@ vec2 AISystem::seek(const AI & ai) { return desired_velocity - rigidbody.data.linear_velocity; } + +vec2 AISystem::flee(const AI & ai) { + const Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; + RefVector transforms = mgr.get_components_by_id(ai.game_object_id); + Transform & transform = transforms.front().get(); + RefVector rigidbodies = mgr.get_components_by_id(ai.game_object_id); + Rigidbody & rigidbody = rigidbodies.front().get(); + + vec2 desired_velocity = transform.position - ai.flee_target; + if (desired_velocity.length_squared() > ai.square_flee_panic_distance) { + return vec2{0, 0}; + } + + desired_velocity.normalize(); + desired_velocity *= rigidbody.data.max_linear_velocity; + + return desired_velocity - rigidbody.data.linear_velocity; +} + +vec2 AISystem::arrive(const AI & ai) { + const Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; + RefVector transforms = mgr.get_components_by_id(ai.game_object_id); + Transform & transform = transforms.front().get(); + RefVector rigidbodies = mgr.get_components_by_id(ai.game_object_id); + Rigidbody & rigidbody = rigidbodies.front().get(); + + vec2 to_target = ai.seek_target - transform.position; + float distance = to_target.length(); + if (distance > 0.0f) { + float speed = distance / ai.arrive_deceleration; + speed = std::min(speed, rigidbody.data.max_linear_velocity.length()); + vec2 desired_velocity = to_target * (speed / distance); + + return desired_velocity - rigidbody.data.linear_velocity; + } + + return vec2{0, 0}; +} diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 144aef3..319d0fe 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -27,7 +27,7 @@ class Script1 : public Script { bool mousemove(const MouseMoveEvent & event) { RefVector aivec = this->get_components(); AI & ai = aivec.front().get(); - ai.seek_target + ai.flee_target = vec2{static_cast(event.mouse_x), static_cast(event.mouse_y)}; return true; } @@ -52,7 +52,9 @@ public: Texture img = Texture("asset/texture/test_ap43.png"); game_object1.add_component(img, Color::MAGENTA, Sprite::FlipSettings{false, false}, 1, 1, 195); - game_object1.add_component(30).seek_on(); + AI & ai = game_object1.add_component(30); + ai.arrive_on(); + ai.flee_on(); game_object1.add_component(Rigidbody::Data{ .mass = 0.5f, .max_linear_velocity = {21, 21}, // sqrt(21^2 + 21^2) = 30 }); -- cgit v1.2.3 From 33a072db28d71ba65e59f9491abd42dbf9695fc4 Mon Sep 17 00:00:00 2001 From: max-001 Date: Fri, 6 Dec 2024 17:14:00 +0100 Subject: Implemented path_follow --- src/crepe/api/AI.h | 14 ++++++++++++++ src/crepe/system/AISystem.cpp | 34 ++++++++++++++++++++++++++++++++-- src/crepe/system/AISystem.h | 2 +- src/example/AITest.cpp | 21 +++++++++++++-------- 4 files changed, 60 insertions(+), 11 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h index d4bd9d3..35b8998 100644 --- a/src/crepe/api/AI.h +++ b/src/crepe/api/AI.h @@ -36,6 +36,8 @@ public: if (on(PATH_FOLLOW)) flags ^= PATH_FOLLOW; } + void add_path_node(vec2 node) { path.push_back(node); } + public: float max_force; @@ -47,9 +49,21 @@ public: float square_flee_panic_distance = 200.0f * 200.0f; // The deceleration rate for the arrive behavior (higher values will make the entity decelerate faster (less overshoot)) float arrive_deceleration = 40.0f; + // The path to follow + std::vector path; + // The distance from the path node at which the entity will move to the next node + float path_node_distance = 400.0f; + // Looping behavior for the path + bool path_loop = true; private: + // The flags for the behaviors int flags = 0; + // The current path index + size_t path_index = 0; + + // The AISystem is the only class that can access the private members of AI + friend class AISystem; }; } // namespace crepe diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index ce3147f..55dc14c 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -55,11 +55,11 @@ vec2 AISystem::calculate(AI & ai) { } } if (ai.on(AI::BehaviorType::PATH_FOLLOW)) { - /*vec2 force_to_add = this->path_follow(ai); + vec2 force_to_add = this->path_follow(ai); if (!this->accumulate_force(ai, force, force_to_add)) { return force; - }*/ + } } return force; @@ -138,3 +138,33 @@ vec2 AISystem::arrive(const AI & ai) { return vec2{0, 0}; } + +vec2 AISystem::path_follow(AI & ai) { + const Mediator & mediator = this->mediator; + ComponentManager & mgr = mediator.component_manager; + RefVector transforms = mgr.get_components_by_id(ai.game_object_id); + Transform & transform = transforms.front().get(); + RefVector rigidbodies = mgr.get_components_by_id(ai.game_object_id); + Rigidbody & rigidbody = rigidbodies.front().get(); + + if (ai.path.empty()) { + return vec2{0, 0}; + } + + vec2 to_target = ai.path.at(ai.path_index) - transform.position; + if (to_target.length_squared() > ai.path_node_distance * ai.path_node_distance) { + ai.seek_target = ai.path.at(ai.path_index); + } else { + ai.path_index++; + if (ai.path_index >= ai.path.size()) { + if (ai.path_loop) { + ai.path_index = 0; + } else { + ai.path_index = ai.path.size() - 1; + return this->arrive(ai); + } + } + } + + return this->seek(ai); +} diff --git a/src/crepe/system/AISystem.h b/src/crepe/system/AISystem.h index 18f1c61..27861d9 100644 --- a/src/crepe/system/AISystem.h +++ b/src/crepe/system/AISystem.h @@ -20,7 +20,7 @@ private: vec2 seek(const AI & ai); vec2 flee(const AI & ai); vec2 arrive(const AI & ai); - vec2 path_follow(const AI & ai); + vec2 path_follow(AI & ai); }; } // namespace crepe diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 319d0fe..d12a99a 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -25,10 +25,10 @@ class Script1 : public Script { } bool mousemove(const MouseMoveEvent & event) { - RefVector aivec = this->get_components(); + /*RefVector aivec = this->get_components(); AI & ai = aivec.front().get(); ai.flee_target - = vec2{static_cast(event.mouse_x), static_cast(event.mouse_y)}; + = vec2{static_cast(event.mouse_x), static_cast(event.mouse_y)};*/ return true; } @@ -46,21 +46,26 @@ public: Mediator & mediator = this->mediator; ComponentManager & mgr = mediator.component_manager; - GameObject game_object1 = mgr.new_object("", "", vec2{250, 250}, 0, 1); + 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(img, Color::MAGENTA, Sprite::FlipSettings{false, false}, 1, 1, 195); - AI & ai = game_object1.add_component(30); - ai.arrive_on(); - ai.flee_on(); + AI & ai = game_object1.add_component(300); + // ai.arrive_on(); + // ai.flee_on(); + ai.path_follow_on(); + ai.add_path_node(vec2{1200, 1200}); + ai.add_path_node(vec2{-1200, 1200}); + ai.add_path_node(vec2{1200, -1200}); + ai.add_path_node(vec2{-1200, -1200}); game_object1.add_component(Rigidbody::Data{ - .mass = 0.5f, .max_linear_velocity = {21, 21}, // sqrt(21^2 + 21^2) = 30 + .mass = 0.5f, .max_linear_velocity = {50, 50}, // sqrt(21^2 + 21^2) = 30 }); game_object1.add_component().set_script(); - game_object2.add_component(Color::WHITE, ivec2{1080, 720}, vec2{1036, 780}, + game_object2.add_component(Color::WHITE, ivec2{1080, 720}, vec2{5000, 5000}, 1.0f); } -- cgit v1.2.3