aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormax-001 <maxsmits21@kpnmail.nl>2024-12-06 16:41:51 +0100
committermax-001 <maxsmits21@kpnmail.nl>2024-12-06 16:41:51 +0100
commit0d0943d23364d7110f0232e3564f4ea63af13db2 (patch)
tree8ae2f2cb22690101b70c1cd5f1b6ea33863eedcf
parent9eac8d31b25c234a21b1d188df17e77e71f48088 (diff)
Implemented flee and arrive behaviors
-rw-r--r--src/crepe/api/AI.h4
-rw-r--r--src/crepe/system/AISystem.cpp71
-rw-r--r--src/example/AITest.cpp6
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
});