diff options
author | max-001 <maxsmits21@kpnmail.nl> | 2024-12-06 16:41:51 +0100 |
---|---|---|
committer | max-001 <maxsmits21@kpnmail.nl> | 2024-12-06 16:41:51 +0100 |
commit | 0d0943d23364d7110f0232e3564f4ea63af13db2 (patch) | |
tree | 8ae2f2cb22690101b70c1cd5f1b6ea33863eedcf | |
parent | 9eac8d31b25c234a21b1d188df17e77e71f48088 (diff) |
Implemented flee and arrive behaviors
-rw-r--r-- | src/crepe/api/AI.h | 4 | ||||
-rw-r--r-- | src/crepe/system/AISystem.cpp | 71 | ||||
-rw-r--r-- | src/example/AITest.cpp | 6 |
3 files changed, 69 insertions, 12 deletions
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 <algorithm> +#include <cmath> + #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<Transform> transforms = mgr.get_components_by_id<Transform>(ai.game_object_id); + Transform & transform = transforms.front().get(); + RefVector<Rigidbody> rigidbodies = mgr.get_components_by_id<Rigidbody>(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<Transform> transforms = mgr.get_components_by_id<Transform>(ai.game_object_id); + Transform & transform = transforms.front().get(); + RefVector<Rigidbody> rigidbodies = mgr.get_components_by_id<Rigidbody>(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<AI> aivec = this->get_components<AI>(); AI & ai = aivec.front().get(); - ai.seek_target + ai.flee_target = vec2{static_cast<float>(event.mouse_x), static_cast<float>(event.mouse_y)}; return true; } @@ -52,7 +52,9 @@ public: Texture img = Texture("asset/texture/test_ap43.png"); game_object1.add_component<Sprite>(img, Color::MAGENTA, Sprite::FlipSettings{false, false}, 1, 1, 195); - game_object1.add_component<AI>(30).seek_on(); + AI & ai = game_object1.add_component<AI>(30); + ai.arrive_on(); + ai.flee_on(); game_object1.add_component<Rigidbody>(Rigidbody::Data{ .mass = 0.5f, .max_linear_velocity = {21, 21}, // sqrt(21^2 + 21^2) = 30 }); |