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 /src | |
| parent | 9eac8d31b25c234a21b1d188df17e77e71f48088 (diff) | |
Implemented flee and arrive behaviors
Diffstat (limited to 'src')
| -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  		}); |