aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/system
diff options
context:
space:
mode:
Diffstat (limited to 'src/crepe/system')
-rw-r--r--src/crepe/system/AISystem.cpp85
-rw-r--r--src/crepe/system/AISystem.h26
-rw-r--r--src/crepe/system/CMakeLists.txt2
-rw-r--r--src/crepe/system/CollisionSystem.cpp38
-rw-r--r--src/crepe/system/CollisionSystem.h6
5 files changed, 133 insertions, 24 deletions
diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp
new file mode 100644
index 0000000..4858000
--- /dev/null
+++ b/src/crepe/system/AISystem.cpp
@@ -0,0 +1,85 @@
+#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"
+
+using namespace crepe;
+
+void AISystem::update() {
+ const Mediator & mediator = this->mediator;
+ ComponentManager & mgr = mediator.component_manager;
+ RefVector<AI> ai_components = mgr.get_components_by_type<AI>();
+
+ double dt = LoopTimer::get_instance().get_delta_time();
+
+ for (AI & ai : ai_components) {
+ RefVector<Rigidbody> rigidbodies
+ = mgr.get_components_by_id<Rigidbody>(ai.game_object_id);
+ Rigidbody & rigidbody = rigidbodies.front().get();
+
+ vec2 force = this->calculate(ai);
+ vec2 acceleration = force / rigidbody.data.mass;
+ rigidbody.data.linear_velocity += acceleration * dt;
+ }
+}
+
+vec2 AISystem::calculate(AI & ai) {
+ vec2 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::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;
+}
+
+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 <= 0.0f) {
+ return false;
+ }
+
+ float magnitude_to_add = force_to_add.length();
+ if (magnitude_to_add < magnitude_remaining) {
+ running_total += force_to_add;
+ } else {
+ force_to_add.normalize();
+ running_total += force_to_add * magnitude_remaining;
+ }
+
+ return true;
+}
+
+vec2 AISystem::seek(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 = ai.seek_target - transform.position;
+ desired_velocity.normalize();
+ desired_velocity *= rigidbody.data.max_linear_velocity;
+
+ return desired_velocity - rigidbody.data.linear_velocity;
+}
diff --git a/src/crepe/system/AISystem.h b/src/crepe/system/AISystem.h
new file mode 100644
index 0000000..18f1c61
--- /dev/null
+++ b/src/crepe/system/AISystem.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "api/AI.h"
+
+#include "System.h"
+#include "types.h"
+
+namespace crepe {
+
+class AISystem : public System {
+public:
+ using System::System;
+
+ void update() override;
+
+private:
+ vec2 calculate(AI & ai);
+ 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
diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt
index 95f6e33..7de5198 100644
--- a/src/crepe/system/CMakeLists.txt
+++ b/src/crepe/system/CMakeLists.txt
@@ -7,6 +7,7 @@ target_sources(crepe PUBLIC
RenderSystem.cpp
AnimatorSystem.cpp
InputSystem.cpp
+ AISystem.cpp
)
target_sources(crepe PUBLIC FILE_SET HEADERS FILES
@@ -17,4 +18,5 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
RenderSystem.h
AnimatorSystem.h
InputSystem.h
+ AISystem.h
)
diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp
index 44ea7ee..2a487fd 100644
--- a/src/crepe/system/CollisionSystem.cpp
+++ b/src/crepe/system/CollisionSystem.cpp
@@ -6,6 +6,8 @@
#include <utility>
#include <variant>
+#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<CollisionInternal> all_colliders;
game_object_id_t id = 0;
ComponentManager & mgr = this->mediator.component_manager;
- RefVector<Rigidbody> rigidbodies
- = mgr.get_components_by_type<Rigidbody>();
+ RefVector<Rigidbody> rigidbodies = mgr.get_components_by_type<Rigidbody>();
// 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<Transform>(id).front().get();
+ Transform & transform = mgr.get_components_by_id<Transform>(id).front().get();
// Check if the boxcollider is active and has the same id as the rigidbody.
- RefVector<BoxCollider> boxcolliders
- = mgr.get_components_by_type<BoxCollider>();
+ RefVector<BoxCollider> boxcolliders = mgr.get_components_by_type<BoxCollider>();
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<CollisionEvent>(
- data, info.this_collider.game_object_id);
+ emgr.trigger_event<CollisionEvent>(data, info.this_collider.game_object_id);
}
void CollisionSystem::static_collision_handler(CollisionInfo & info) {
@@ -389,14 +385,14 @@ CollisionSystem::gather_collisions(std::vector<CollisionInternal> & colliders) {
bool CollisionSystem::have_common_layer(const std::set<int> & layers1,
const std::set<int> & 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;
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.