aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/crepe/api/AI.h10
-rw-r--r--src/crepe/system/AISystem.cpp23
2 files changed, 27 insertions, 6 deletions
diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h
index 18276a1..0dccd5f 100644
--- a/src/crepe/api/AI.h
+++ b/src/crepe/api/AI.h
@@ -30,7 +30,7 @@ public:
AI(game_object_id_t id, float max_force);
/**
- * \brief Check if a behavior is on/activated
+ * \brief Check if a behavior is on (aka activated)
*
* \param behavior The behavior to check
* \return true if the behavior is on, false otherwise
@@ -62,7 +62,7 @@ public:
}
/**
- * \brief Add a path node
+ * \brief Add a path node (for the path following behavior)
*
* \note The path is not relative to the entity's position (it is an absolute path)
*
@@ -70,7 +70,7 @@ public:
*/
void add_path_node(vec2 node) { path.push_back(node); }
/**
- * \brief Make a circle path
+ * \brief Make a circle path (for the path following behavior)
*
* \note The path is not relative to the entity's position (it is an absolute path)
*
@@ -94,9 +94,9 @@ 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
+ //! The path to follow (for the path following behavior)
std::vector<vec2> path;
- //! The distance from the path node at which the entity will move to the next node
+ //! The distance from the path node at which the entity will move to the next node (automatically set by make_circle_path())
float path_node_distance = 400.0f;
//! Looping behavior for the path
bool path_loop = true;
diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp
index 72f3d9b..8be5ddc 100644
--- a/src/crepe/system/AISystem.cpp
+++ b/src/crepe/system/AISystem.cpp
@@ -20,13 +20,21 @@ void AISystem::update() {
//TODO: Use fixed loop dt (this is not available at master at the moment)
double dt = LoopTimer::get_instance().get_delta_time();
+ // Loop through all AI components
for (AI & ai : ai_components) {
+ if (!ai.active) {
+ continue;
+ }
+
RefVector<Rigidbody> rigidbodies
= mgr.get_components_by_id<Rigidbody>(ai.game_object_id);
Rigidbody & rigidbody = rigidbodies.front().get();
+ // Calculate the force to apply to the entity
vec2 force = this->calculate(ai);
+ // Calculate the acceleration (using the above calculated force)
vec2 acceleration = force / rigidbody.data.mass;
+ // Finally, update Rigidbody's velocity
rigidbody.data.linear_velocity += acceleration * dt;
}
}
@@ -34,6 +42,7 @@ void AISystem::update() {
vec2 AISystem::calculate(AI & ai) {
vec2 force;
+ // Run all the behaviors that are on, and stop if the force gets too high
if (ai.on(AI::BehaviorType::FLEE)) {
vec2 force_to_add = this->flee(ai);
@@ -71,13 +80,16 @@ bool AISystem::accumulate_force(AI & ai, vec2 & running_total, vec2 force_to_add
float magnitude_remaining = ai.max_force - magnitude;
if (magnitude_remaining <= 0.0f) {
+ // If the force is already at/above the max force, return false
return false;
}
float magnitude_to_add = force_to_add.length();
if (magnitude_to_add < magnitude_remaining) {
+ // If the force to add is less than the remaining force, add it
running_total += force_to_add;
} else {
+ // If the force to add is greater than the remaining force, add a fraction of it
force_to_add.normalize();
running_total += force_to_add * magnitude_remaining;
}
@@ -93,6 +105,7 @@ vec2 AISystem::seek(const AI & ai) {
RefVector<Rigidbody> rigidbodies = mgr.get_components_by_id<Rigidbody>(ai.game_object_id);
Rigidbody & rigidbody = rigidbodies.front().get();
+ // Calculate the desired velocity
vec2 desired_velocity = ai.seek_target - transform.position;
desired_velocity.normalize();
desired_velocity *= rigidbody.data.max_linear_velocity;
@@ -108,11 +121,11 @@ vec2 AISystem::flee(const AI & ai) {
RefVector<Rigidbody> rigidbodies = mgr.get_components_by_id<Rigidbody>(ai.game_object_id);
Rigidbody & rigidbody = rigidbodies.front().get();
+ // Calculate the desired velocity if the entity is within the panic distance
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;
@@ -127,6 +140,7 @@ vec2 AISystem::arrive(const AI & ai) {
RefVector<Rigidbody> rigidbodies = mgr.get_components_by_id<Rigidbody>(ai.game_object_id);
Rigidbody & rigidbody = rigidbodies.front().get();
+ // Calculate the desired velocity (taking into account the deceleration rate)
vec2 to_target = ai.seek_target - transform.position;
float distance = to_target.length();
if (distance > 0.0f) {
@@ -152,21 +166,28 @@ vec2 AISystem::path_follow(AI & ai) {
return vec2{0, 0};
}
+ // Get the target node
vec2 target = ai.path.at(ai.path_index);
+ // Calculate the force to apply to the entity
vec2 to_target = target - transform.position;
if (to_target.length_squared() > ai.path_node_distance * ai.path_node_distance) {
+ // If the entity is not close enough to the target node, seek it
ai.seek_target = target;
} else {
+ // If the entity is close enough to the target node, move to the next node
ai.path_index++;
if (ai.path_index >= ai.path.size()) {
if (ai.path_loop) {
+ // If the path is looping, reset the path index
ai.path_index = 0;
} else {
+ // If the path is not looping, arrive at the last node
ai.path_index = ai.path.size() - 1;
return this->arrive(ai);
}
}
}
+ // Seek the target node
return this->seek(ai);
}