Behaviors cleanup part2.

This commit is contained in:
Relintai 2023-01-14 02:31:42 +01:00
parent 9bca0fae16
commit 6f27129fe5
13 changed files with 185 additions and 311 deletions

View File

@ -19,6 +19,7 @@ public:
void arrive(const GSAITargetAcceleration &acceleration, const Vector3 &target_position); void arrive(const GSAITargetAcceleration &acceleration, const Vector3 &target_position);
void _arrive(const GSAITargetAcceleration &acceleration, const Vector3 &target_position); void _arrive(const GSAITargetAcceleration &acceleration, const Vector3 &target_position);
void _calculate_steering(const GSAITargetAcceleration &acceleration); void _calculate_steering(const GSAITargetAcceleration &acceleration);
GSAIArrive(); GSAIArrive();

View File

@ -1,96 +1,45 @@
#include "gsai_avoid_collisions.h" #include "gsai_avoid_collisions.h"
GSAISteeringAgent GSAIAvoidCollisions::get_ *_first_neighbor() { #include "../gsai_steering_agent.h"
return *_first_neighbor; #include "../gsai_target_acceleration.h"
} #include "../proximities/gsai_proximity.h"
void GSAIAvoidCollisions::set_ *_first_neighbor(const GSAISteeringAgent &val) { #include "core/math/math_defs.h"
*_first_neighbor = val; #include "core/math/math_funcs.h"
}
float GSAIAvoidCollisions::get__shortest_time() const { void GSAIAvoidCollisions::_calculate_steering(Ref<GSAITargetAcceleration> acceleration) {
return _shortest_time; ERR_FAIL_COND(!proximity.is_valid());
} ERR_FAIL_COND(!agent.is_valid());
void GSAIAvoidCollisions::set__shortest_time(const float val) { _shortest_time = Math_INF;
_shortest_time = val; _first_neighbor.unref();
}
float GSAIAvoidCollisions::get__first_minimum_separation() const {
return _first_minimum_separation;
}
void GSAIAvoidCollisions::set__first_minimum_separation(const float val) {
_first_minimum_separation = val;
}
float GSAIAvoidCollisions::get__first_distance() const {
return _first_distance;
}
void GSAIAvoidCollisions::set__first_distance(const float val) {
_first_distance = val;
}
Vector3 GSAIAvoidCollisions::get__first_relative_position() {
return _first_relative_position;
}
void GSAIAvoidCollisions::set__first_relative_position(const Vector3 &val) {
_first_relative_position = val;
}
Vector3 GSAIAvoidCollisions::get__first_relative_velocity() {
return _first_relative_velocity;
}
void GSAIAvoidCollisions::set__first_relative_velocity(const Vector3 &val) {
_first_relative_velocity = val;
}
// Steers the agent to avoid obstacles in its path. Approximates obstacles as;
// spheres.;
// @category - Group behaviors;
GSAISteeringAgent *_first_neighbor;
float _shortest_time = 0.0;
float _first_minimum_separation = 0.0;
float _first_distance = 0.0;
Vector3 _first_relative_position = ;
Vector3 _first_relative_velocity = ;
void GSAIAvoidCollisions::_calculate_steering(const GSAITargetAcceleration &acceleration) {
_shortest_time = INF;
_first_neighbor = null;
_first_minimum_separation = 0; _first_minimum_separation = 0;
_first_distance = 0; _first_distance = 0;
int neighbor_count = proximity.find_neighbors(_callback); int neighbor_count = proximity->find_neighbors(_callback);
if (neighbor_count == 0 || not _first_neighbor) { Vector3 linear = acceleration->get_linear();
acceleration.set_zero();
}
else { if (neighbor_count == 0 || !_first_neighbor.is_valid()) {
if ((_first_minimum_separation <= 0 || _first_distance < agent.bounding_radius + _first_neighbor.bounding_radius)) { acceleration->set_zero();
acceleration.linear = _first_neighbor.position - agent.position; } else {
} if ((_first_minimum_separation <= 0 || _first_distance < agent->get_bounding_radius() + _first_neighbor->get_bounding_radius())) {
linear = _first_neighbor->get_position() - agent->get_position();
else { } else {
acceleration.linear = (_first_relative_position + (_first_relative_velocity * _shortest_time)); linear = (_first_relative_position + (_first_relative_velocity * _shortest_time));
} }
} }
acceleration.linear = (acceleration.linear.normalized() * -agent.linear_acceleration_max); linear = (linear.normalized() * -agent->get_linear_acceleration_max());
acceleration.angular = 0; acceleration->set_linear(linear);
acceleration->set_angular(0);
} }
// Callback for the proximity to call when finding neighbors. Keeps track of every `neighbor`; bool GSAIAvoidCollisions::_report_neighbor(Ref<GSAISteeringAgent> neighbor) {
// that was found but only keeps the one the owning agent will most likely collide with.; ERR_FAIL_COND_V(!agent.is_valid(), false);
// @tags - virtual;
bool GSAIAvoidCollisions::_report_neighbor(const GSAISteeringAgent &neighbor) { Vector3 relative_position = neighbor->get_position() - agent->get_position();
Vector3 relative_position = neighbor.position - agent.position; Vector3 relative_velocity = neighbor->get_linear_velocity() - agent->get_linear_velocity();
Vector3 relative_velocity = neighbor.linear_velocity - agent.linear_velocity;
float relative_speed_squared = relative_velocity.length_squared(); float relative_speed_squared = relative_velocity.length_squared();
if (relative_speed_squared == 0) { if (relative_speed_squared == 0) {
@ -102,17 +51,13 @@ bool GSAIAvoidCollisions::_report_neighbor(const GSAISteeringAgent &neighbor) {
if (time_to_collision <= 0 || time_to_collision >= _shortest_time) { if (time_to_collision <= 0 || time_to_collision >= _shortest_time) {
return false; return false;
} } else {
float distance = relative_position.length();
float minimum_separation = (distance - Math::sqrt(relative_speed_squared) * time_to_collision);
else { if (minimum_separation > agent->get_bounding_radius() + neighbor->get_bounding_radius()) {
Variant = relative_position.length();
float minimum_separation = (distance - sqrt(relative_speed_squared) * time_to_collision);
if (minimum_separation > agent.bounding_radius + neighbor.bounding_radius) {
return false; return false;
} } else {
else {
_shortest_time = time_to_collision; _shortest_time = time_to_collision;
_first_neighbor = neighbor; _first_neighbor = neighbor;
_first_minimum_separation = minimum_separation; _first_minimum_separation = minimum_separation;
@ -124,45 +69,15 @@ bool GSAIAvoidCollisions::_report_neighbor(const GSAISteeringAgent &neighbor) {
} }
} }
} }
}
GSAIAvoidCollisions::GSAIAvoidCollisions() { GSAIAvoidCollisions::GSAIAvoidCollisions() {
*_first_neighbor;
_shortest_time = 0.0; _shortest_time = 0.0;
_first_minimum_separation = 0.0; _first_minimum_separation = 0.0;
_first_distance = 0.0; _first_distance = 0.0;
_first_relative_position = ;
_first_relative_velocity = ;
} }
GSAIAvoidCollisions::~GSAIAvoidCollisions() { GSAIAvoidCollisions::~GSAIAvoidCollisions() {
} }
static void GSAIAvoidCollisions::_bind_methods() { void GSAIAvoidCollisions::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_*_first_neighbor"), &GSAIAvoidCollisions::get_ * _first_neighbor);
ClassDB::bind_method(D_METHOD("set_*_first_neighbor", "value"), &GSAIAvoidCollisions::set_ * _first_neighbor);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "*_first_neighbor", PROPERTY_HINT_RESOURCE_TYPE, "GSAISteeringAgent"), "set_*_first_neighbor", "get_*_first_neighbor");
ClassDB::bind_method(D_METHOD("get__shortest_time"), &GSAIAvoidCollisions::get__shortest_time);
ClassDB::bind_method(D_METHOD("set__shortest_time", "value"), &GSAIAvoidCollisions::set__shortest_time);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "_shortest_time"), "set__shortest_time", "get__shortest_time");
ClassDB::bind_method(D_METHOD("get__first_minimum_separation"), &GSAIAvoidCollisions::get__first_minimum_separation);
ClassDB::bind_method(D_METHOD("set__first_minimum_separation", "value"), &GSAIAvoidCollisions::set__first_minimum_separation);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "_first_minimum_separation"), "set__first_minimum_separation", "get__first_minimum_separation");
ClassDB::bind_method(D_METHOD("get__first_distance"), &GSAIAvoidCollisions::get__first_distance);
ClassDB::bind_method(D_METHOD("set__first_distance", "value"), &GSAIAvoidCollisions::set__first_distance);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "_first_distance"), "set__first_distance", "get__first_distance");
ClassDB::bind_method(D_METHOD("get__first_relative_position"), &GSAIAvoidCollisions::get__first_relative_position);
ClassDB::bind_method(D_METHOD("set__first_relative_position", "value"), &GSAIAvoidCollisions::set__first_relative_position);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "_first_relative_position"), "set__first_relative_position", "get__first_relative_position");
ClassDB::bind_method(D_METHOD("get__first_relative_velocity"), &GSAIAvoidCollisions::get__first_relative_velocity);
ClassDB::bind_method(D_METHOD("set__first_relative_velocity", "value"), &GSAIAvoidCollisions::set__first_relative_velocity);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "_first_relative_velocity"), "set__first_relative_velocity", "get__first_relative_velocity");
ClassDB::bind_method(D_METHOD("_calculate_steering", "acceleration"), &GSAIAvoidCollisions::_calculate_steering);
ClassDB::bind_method(D_METHOD("_report_neighbor", "neighbor"), &GSAIAvoidCollisions::_report_neighbor);
} }

View File

@ -1,30 +1,19 @@
#ifndef GSAI_AVOID_COLLISIONS_H #ifndef GSAI_AVOID_COLLISIONS_H
#define GSAI_AVOID_COLLISIONS_H #define GSAI_AVOID_COLLISIONS_H
#include "core/object/reference.h"
#include "../gsai_group_behavior.h"
class GSAITargetAcceleration;
class GSAISteeringAgent;
class GSAIAvoidCollisions : public GSAIGroupBehavior { class GSAIAvoidCollisions : public GSAIGroupBehavior {
GDCLASS(GSAIAvoidCollisions, GSAIGroupBehavior); GDCLASS(GSAIAvoidCollisions, GSAIGroupBehavior);
public: public:
GSAISteeringAgent get_ *_first_neighbor(); void _calculate_steering(Ref<GSAITargetAcceleration> acceleration);
void set_ *_first_neighbor(const GSAISteeringAgent &val); bool _report_neighbor(Ref<GSAISteeringAgent> neighbor);
float get__shortest_time() const;
void set__shortest_time(const float val);
float get__first_minimum_separation() const;
void set__first_minimum_separation(const float val);
float get__first_distance() const;
void set__first_distance(const float val);
Vector3 get__first_relative_position();
void set__first_relative_position(const Vector3 &val);
Vector3 get__first_relative_velocity();
void set__first_relative_velocity(const Vector3 &val);
void _calculate_steering(const GSAITargetAcceleration &acceleration);
bool _report_neighbor(const GSAISteeringAgent &neighbor);
GSAIAvoidCollisions(); GSAIAvoidCollisions();
~GSAIAvoidCollisions(); ~GSAIAvoidCollisions();
@ -35,15 +24,12 @@ protected:
// Steers the agent to avoid obstacles in its path. Approximates obstacles as // Steers the agent to avoid obstacles in its path. Approximates obstacles as
// spheres. // spheres.
// @category - Group behaviors // @category - Group behaviors
GSAISteeringAgent *_first_neighbor; Ref<GSAISteeringAgent> _first_neighbor;
float _shortest_time = 0.0; float _shortest_time;
float _first_minimum_separation = 0.0; float _first_minimum_separation;
float _first_distance = 0.0; float _first_distance;
Vector3 _first_relative_position = ; Vector3 _first_relative_position;
Vector3 _first_relative_velocity = ; Vector3 _first_relative_velocity;
// Callback for the proximity to call when finding neighbors. Keeps track of every `neighbor`
// that was found but only keeps the one the owning agent will most likely collide with.
// @tags - virtual
}; };
#endif #endif

View File

@ -1,108 +1,73 @@
#include "gsai_blend.h" #include "gsai_blend.h"
Array GSAIBlend::get__behaviors() { #include "../gsai_steering_agent.h"
return _behaviors; #include "../gsai_target_acceleration.h"
#include "../gsai_utils.h"
void GSAIBlend::add_behavior(const Ref<GSAISteeringBehavior> &behavior, const float weight) {
ERR_FAIL_COND(!behavior.is_valid());
GSAIBlendBehaviorEntry e;
e.behavior = behavior;
e.weight = weight;
_behaviors.push_back(e);
} }
void GSAIBlend::set__behaviors(const Array &val) { Ref<GSAISteeringBehavior> GSAIBlend::get_behavior(const int index) {
_behaviors = val; ERR_FAIL_INDEX_V(index, _behaviors.size(), Ref<GSAISteeringBehavior>());
return _behaviors[index].behavior;
} }
GSAITargetAcceleration GSAIBlend::get_ *_accel() { float GSAIBlend::get_behavior_weight(const int index) {
return *_accel; ERR_FAIL_INDEX_V(index, _behaviors.size(), 0);
}
void GSAIBlend::set_ *_accel(const GSAITargetAcceleration &val) { return _behaviors[index].weight;
*_accel = val;
}
// Blends multiple steering behaviors into one, and returns a weighted;
// acceleration from their calculations.;
//;
// Stores the behaviors internally as dictionaries of the form;
// {;
// behavior : GSAISteeringBehavior,;
// weight : float;
// };
// @category - Combination behaviors;
Array _behaviors = Array();
GSAITargetAcceleration *_accel = GSAITargetAcceleration.new();
// Appends a behavior to the internal array along with its `weight`.;
void GSAIBlend::add_behavior(const GSAISteeringBehavior &behavior, const float weight) {
behavior.agent = agent;
Dictionary dict = Dictionary();
dict["behavior"] = behavior;
dict["weight"] = weight;
_behaviors.append(dict);
}
// Returns the behavior at the specified `index`, or an empty `Dictionary` if;
// none was found.;
Dictionary GSAIBlend::get_behavior(const int index) {
if (_behaviors.size() > index) {
return _behaviors[index];
}
printerr("Tried to get index " + str(index) + " in array of size " + str(_behaviors.size()));
return Dictionary();
} }
void GSAIBlend::remove_behavior(const int index) { void GSAIBlend::remove_behavior(const int index) {
if (_behaviors.size() > index) { ERR_FAIL_INDEX(index, _behaviors.size());
_behaviors.remove(index);
return;
}
printerr("Tried to get index " + str(index) + " in array of size " + str(_behaviors.size())); _behaviors.remove(index);
return;
} }
int GSAIBlend::get_behaviour_count() { int GSAIBlend::get_behaviour_count() {
return _behaviors.size(); return _behaviors.size();
} }
GSAITargetAcceleration GSAIBlend::get_accel() { Ref<GSAITargetAcceleration> GSAIBlend::get_accel() {
return _accel; return _accel;
} }
void GSAIBlend::_calculate_steering(const GSAITargetAcceleration &blended_accel) { void GSAIBlend::_calculate_steering(Ref<GSAITargetAcceleration> blended_accel) {
blended_accel.set_zero(); ERR_FAIL_COND(!agent.is_valid());
blended_accel->set_zero();
for (int i = 0; i < _behaviors.size(); ++i) { //i in range(_behaviors.size()) for (int i = 0; i < _behaviors.size(); ++i) { //i in range(_behaviors.size())
Dictionary bw = _behaviors[i]; GSAIBlendBehaviorEntry bw = _behaviors[i];
bw.behavior.calculate_steering(_accel);
blended_accel.add_scaled_accel(_accel, bw.weight); bw.behavior->calculate_steering(_accel);
blended_accel->add_scaled_accel(_accel, bw.weight);
} }
blended_accel.linear = GSAIUtils.clampedv3(blended_accel.linear, agent.linear_acceleration_max); blended_accel->set_linear(GSAIUtils::clampedv3(blended_accel->get_linear(), agent->get_linear_acceleration_max()));
blended_accel.angular = clamp(blended_accel.angular, -agent.angular_acceleration_max, agent.angular_acceleration_max); float angular_acceleration_max = agent->get_angular_acceleration_max();
} blended_accel->set_angular(CLAMP(blended_accel->get_angular(), -angular_acceleration_max, angular_acceleration_max));
} }
GSAIBlend::GSAIBlend() { GSAIBlend::GSAIBlend() {
_behaviors = Array(); _accel.instance();
*_accel = GSAITargetAcceleration.new();
} }
GSAIBlend::~GSAIBlend() { GSAIBlend::~GSAIBlend() {
} }
static void GSAIBlend::_bind_methods() { void GSAIBlend::_bind_methods() {
ClassDB::bind_method(D_METHOD("get__behaviors"), &GSAIBlend::get__behaviors);
ClassDB::bind_method(D_METHOD("set__behaviors", "value"), &GSAIBlend::set__behaviors);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_behaviors"), "set__behaviors", "get__behaviors");
ClassDB::bind_method(D_METHOD("get_*_accel"), &GSAIBlend::get_ * _accel);
ClassDB::bind_method(D_METHOD("set_*_accel", "value"), &GSAIBlend::set_ * _accel);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "*_accel", PROPERTY_HINT_RESOURCE_TYPE, "GSAITargetAcceleration"), "set_*_accel", "get_*_accel");
ClassDB::bind_method(D_METHOD("add_behavior", "behavior", "weight"), &GSAIBlend::add_behavior); ClassDB::bind_method(D_METHOD("add_behavior", "behavior", "weight"), &GSAIBlend::add_behavior);
ClassDB::bind_method(D_METHOD("get_behavior", "index"), &GSAIBlend::get_behavior); ClassDB::bind_method(D_METHOD("get_behavior", "index"), &GSAIBlend::get_behavior);
ClassDB::bind_method(D_METHOD("remove_behavior", "index"), &GSAIBlend::remove_behavior); ClassDB::bind_method(D_METHOD("remove_behavior", "index"), &GSAIBlend::remove_behavior);
ClassDB::bind_method(D_METHOD("get_behaviour_count"), &GSAIBlend::get_behaviour_count); ClassDB::bind_method(D_METHOD("get_behaviour_count"), &GSAIBlend::get_behaviour_count);
ClassDB::bind_method(D_METHOD("get_accel"), &GSAIBlend::get_accel); ClassDB::bind_method(D_METHOD("get_accel"), &GSAIBlend::get_accel);
ClassDB::bind_method(D_METHOD("_calculate_steering", "blended_accel"), &GSAIBlend::_calculate_steering);
} }

View File

@ -1,40 +1,44 @@
#ifndef GSAI_BLEND_H #ifndef GSAI_BLEND_H
#define GSAI_BLEND_H #define GSAI_BLEND_H
#include "core/object/reference.h"
#include "../gsai_steering_behavior.h"
class GSAISteeringBehavior;
class GSAITargetAcceleration;
class GSAIBlend : public GSAISteeringBehavior { class GSAIBlend : public GSAISteeringBehavior {
GDCLASS(GSAIBlend, GSAISteeringBehavior); GDCLASS(GSAIBlend, GSAISteeringBehavior);
public: public:
Array get__behaviors(); void add_behavior(const Ref<GSAISteeringBehavior> &behavior, const float weight);
void set__behaviors(const Array &val); Ref<GSAISteeringBehavior> get_behavior(const int index);
float get_behavior_weight(const int index);
GSAITargetAcceleration get_ *_accel();
void set_ *_accel(const GSAITargetAcceleration &val);
void add_behavior(const GSAISteeringBehavior &behavior, const float weight);
Dictionary get_behavior(const int index);
void remove_behavior(const int index); void remove_behavior(const int index);
int get_behaviour_count(); int get_behaviour_count();
GSAITargetAcceleration get_accel();
void _calculate_steering(const GSAITargetAcceleration &blended_accel); Ref<GSAITargetAcceleration> get_accel();
void _calculate_steering(Ref<GSAITargetAcceleration> blended_accel);
GSAIBlend(); GSAIBlend();
~GSAIBlend(); ~GSAIBlend();
protected:
struct GSAIBlendBehaviorEntry {
Ref<GSAISteeringBehavior> behavior;
float weight;
};
protected: protected:
static void _bind_methods(); static void _bind_methods();
// Blends multiple steering behaviors into one, and returns a weighted // Blends multiple steering behaviors into one, and returns a weighted
// acceleration from their calculations. // acceleration from their calculations.
//
// Stores the behaviors internally as dictionaries of the form
// {
// behavior : GSAISteeringBehavior,
// weight : float
// }
// @category - Combination behaviors // @category - Combination behaviors
Array _behaviors = Array(); Vector<GSAIBlendBehaviorEntry> _behaviors;
GSAITargetAcceleration *_accel = GSAITargetAcceleration.new(); Ref<GSAITargetAcceleration> _accel;
// Appends a behavior to the internal array along with its `weight`. // Appends a behavior to the internal array along with its `weight`.
// Returns the behavior at the specified `index`, or an empty `Dictionary` if // Returns the behavior at the specified `index`, or an empty `Dictionary` if
// none was found. // none was found.

View File

@ -1,52 +1,34 @@
#include "gsai_cohesion.h" #include "gsai_cohesion.h"
Vector3 GSAICohesion::get__center_of_mass() { #include "../gsai_steering_agent.h"
return _center_of_mass; #include "../gsai_target_acceleration.h"
} #include "../proximities/gsai_proximity.h"
void GSAICohesion::set__center_of_mass(const Vector3 &val) { void GSAICohesion::_calculate_steering(Ref<GSAITargetAcceleration> acceleration) {
_center_of_mass = val; ERR_FAIL_COND(!proximity.is_valid());
} ERR_FAIL_COND(!agent.is_valid());
// Calculates an acceleration that attempts to move the agent towards the center; acceleration->set_zero();
// of mass of the agents in the area defined by the `GSAIProximity`.; _center_of_mass = Vector3();
// @category - Group behaviors; int neighbor_count = proximity->find_neighbors(_callback);
Vector3 _center_of_mass = ;
void GSAICohesion::_calculate_steering(const GSAITargetAcceleration &acceleration) {
acceleration.set_zero();
_center_of_mass = Vector3.ZERO;
Variant = proximity.find_neighbors(_callback);
if (neighbor_count > 0) { if (neighbor_count > 0) {
_center_of_mass *= 1.0 / neighbor_count; _center_of_mass *= 1.0 / neighbor_count;
acceleration.linear = ((_center_of_mass - agent.position).normalized() * agent.linear_acceleration_max); acceleration->set_linear((_center_of_mass - agent->get_position()).normalized() * agent->get_linear_acceleration_max());
} }
// Callback for the proximity to call when finding neighbors. Adds `neighbor`'s position;
// to the center of mass of the group.;
// @tags - virtual;
} }
bool GSAICohesion::_report_neighbor(const GSAISteeringAgent &neighbor) { bool GSAICohesion::_report_neighbor(Ref<GSAISteeringAgent> neighbor) {
_center_of_mass += neighbor.position; _center_of_mass += neighbor->get_position();
return true; return true;
} }
}
GSAICohesion::GSAICohesion() { GSAICohesion::GSAICohesion() {
_center_of_mass = ;
} }
GSAICohesion::~GSAICohesion() { GSAICohesion::~GSAICohesion() {
} }
static void GSAICohesion::_bind_methods() { void GSAICohesion::_bind_methods() {
ClassDB::bind_method(D_METHOD("get__center_of_mass"), &GSAICohesion::get__center_of_mass);
ClassDB::bind_method(D_METHOD("set__center_of_mass", "value"), &GSAICohesion::set__center_of_mass);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "_center_of_mass"), "set__center_of_mass", "get__center_of_mass");
ClassDB::bind_method(D_METHOD("_calculate_steering", "acceleration"), &GSAICohesion::_calculate_steering);
ClassDB::bind_method(D_METHOD("_report_neighbor", "neighbor"), &GSAICohesion::_report_neighbor);
} }

View File

@ -1,15 +1,19 @@
#ifndef GSAI_COHESION_H #ifndef GSAI_COHESION_H
#define GSAI_COHESION_H #define GSAI_COHESION_H
#include "core/object/reference.h"
#include "../gsai_group_behavior.h"
class GSAITargetAcceleration;
class GSAISteeringAgent;
class GSAICohesion : public GSAIGroupBehavior { class GSAICohesion : public GSAIGroupBehavior {
GDCLASS(GSAICohesion, GSAIGroupBehavior); GDCLASS(GSAICohesion, GSAIGroupBehavior);
public: public:
Vector3 get__center_of_mass(); void _calculate_steering(Ref<GSAITargetAcceleration> acceleration);
void set__center_of_mass(const Vector3 &val); bool _report_neighbor(Ref<GSAISteeringAgent> neighbor);
void _calculate_steering(const GSAITargetAcceleration &acceleration);
bool _report_neighbor(const GSAISteeringAgent &neighbor);
GSAICohesion(); GSAICohesion();
~GSAICohesion(); ~GSAICohesion();
@ -20,7 +24,7 @@ protected:
// Calculates an acceleration that attempts to move the agent towards the center // Calculates an acceleration that attempts to move the agent towards the center
// of mass of the agents in the area defined by the `GSAIProximity`. // of mass of the agents in the area defined by the `GSAIProximity`.
// @category - Group behaviors // @category - Group behaviors
Vector3 _center_of_mass = ; Vector3 _center_of_mass;
}; };
#endif #endif

View File

@ -1,13 +1,12 @@
#include "gsai_evade.h" #include "gsai_evade.h"
// Calculates acceleration to take an agent away from where a target agent is; #include "../gsai_steering_agent.h"
// moving.;
// @category - Individual behaviors;
float GSAIEvade::_get_modified_acceleration() { float GSAIEvade::_get_modified_acceleration() {
return -agent.linear_acceleration_max; ERR_FAIL_COND_V(!agent.is_valid(), 0);
}
return -(agent->get_linear_acceleration_max());
} }
GSAIEvade::GSAIEvade() { GSAIEvade::GSAIEvade() {
@ -16,6 +15,5 @@ GSAIEvade::GSAIEvade() {
GSAIEvade::~GSAIEvade() { GSAIEvade::~GSAIEvade() {
} }
static void GSAIEvade::_bind_methods() { void GSAIEvade::_bind_methods() {
ClassDB::bind_method(D_METHOD("_get_modified_acceleration"), &GSAIEvade::_get_modified_acceleration);
} }

View File

@ -1,6 +1,10 @@
#ifndef GSAI_EVADE_H #ifndef GSAI_EVADE_H
#define GSAI_EVADE_H #define GSAI_EVADE_H
#include "core/object/reference.h"
#include "gsai_pursue.h"
class GSAIEvade : public GSAIPursue { class GSAIEvade : public GSAIPursue {
GDCLASS(GSAIEvade, GSAIPursue); GDCLASS(GSAIEvade, GSAIPursue);

View File

@ -1,40 +1,40 @@
#include "gsai_face.h" #include "gsai_face.h"
// Calculates angular acceleration to rotate a target to face its target's; #include "../gsai_steering_agent.h"
// position. The behavior attemps to arrive with zero remaining angular velocity.;
// @category - Individual behaviors;
void GSAIFace::face(const GSAITargetAcceleration &acceleration, const Vector3 &target_position) { #include "../gsai_target_acceleration.h"
#include "../gsai_utils.h"
void GSAIFace::face(const Ref<GSAITargetAcceleration> &acceleration, const Vector3 &target_position) {
call("_face", acceleration, target_position); call("_face", acceleration, target_position);
} }
void GSAIFace::_face(const GSAITargetAcceleration &acceleration, const Vector3 &target_position) { void GSAIFace::_face(Ref<GSAITargetAcceleration> acceleration, Vector3 target_position) {
Vector3 to_target = target_position - agent.position; ERR_FAIL_COND(!agent.is_valid());
Vector3 to_target = target_position - agent->get_position();
float distance_squared = to_target.length_squared(); float distance_squared = to_target.length_squared();
if (distance_squared < agent.zero_linear_speed_threshold) { if (distance_squared < agent->get_zero_linear_speed_threshold()) {
acceleration.set_zero(); acceleration->set_zero();
} } else {
float orientation;
else {
float orientation = ;
if (use_z) { if (use_z) {
orientation = GSAIUtils.vector3_to_angle(to_target); orientation = GSAIUtils::vector3_to_angle(to_target);
} } else {
orientation = GSAIUtils::vector2_to_angle(GSAIUtils::to_vector2(to_target));
else {
orientation = GSAIUtils.vector2_to_angle(GSAIUtils.to_vector2(to_target));
} }
match_orientation(acceleration, orientation); match_orientation(acceleration, orientation);
} }
} }
void GSAIFace::_calculate_steering(const GSAITargetAcceleration &acceleration) { void GSAIFace::_calculate_steering(Ref<GSAITargetAcceleration> acceleration) {
face(acceleration, target.position); ERR_FAIL_COND(!target.is_valid());
}
face(acceleration, target->get_position());
} }
GSAIFace::GSAIFace() { GSAIFace::GSAIFace() {
@ -43,8 +43,8 @@ GSAIFace::GSAIFace() {
GSAIFace::~GSAIFace() { GSAIFace::~GSAIFace() {
} }
static void GSAIFace::_bind_methods() { void GSAIFace::_bind_methods() {
BIND_VMETHOD(MethodInfo("_face", PropertyInfo(Variant::OBJECT, "acceleration", PROPERTY_HINT_RESOURCE_TYPE, "GSAITargetAcceleration"), PropertyInfo(Variant::VECTOR3, "target_position")));
ClassDB::bind_method(D_METHOD("face", "acceleration", "target_position"), &GSAIFace::face); ClassDB::bind_method(D_METHOD("face", "acceleration", "target_position"), &GSAIFace::face);
ClassDB::bind_method(D_METHOD("_face", "acceleration", "target_position"), &GSAIFace::_face); ClassDB::bind_method(D_METHOD("_face", "acceleration", "target_position"), &GSAIFace::_face);
ClassDB::bind_method(D_METHOD("_calculate_steering", "acceleration"), &GSAIFace::_calculate_steering);
} }

View File

@ -1,13 +1,20 @@
#ifndef GSAI_FACE_H #ifndef GSAI_FACE_H
#define GSAI_FACE_H #define GSAI_FACE_H
#include "core/object/reference.h"
#include "gsai_match_orientation.h"
class GSAITargetAcceleration;
class GSAIFace : public GSAIMatchOrientation { class GSAIFace : public GSAIMatchOrientation {
GDCLASS(GSAIFace, GSAIMatchOrientation); GDCLASS(GSAIFace, GSAIMatchOrientation);
public: public:
void face(const GSAITargetAcceleration &acceleration, const Vector3 &target_position); void face(const Ref<GSAITargetAcceleration> &acceleration, const Vector3 &target_position);
void _face(const GSAITargetAcceleration &acceleration, const Vector3 &target_position); void _face(Ref<GSAITargetAcceleration> acceleration, Vector3 target_position);
void _calculate_steering(const GSAITargetAcceleration &acceleration);
void _calculate_steering(Ref<GSAITargetAcceleration> acceleration);
GSAIFace(); GSAIFace();
~GSAIFace(); ~GSAIFace();

View File

@ -1,13 +1,16 @@
#include "gsai_flee.h" #include "gsai_flee.h"
// Calculates acceleration to take an agent directly away from a target agent.; #include "../gsai_agent_location.h"
// @category - Individual behaviors; #include "../gsai_steering_agent.h"
#include "../gsai_target_acceleration.h"
void GSAIFlee::_calculate_steering(const GSAITargetAcceleration &acceleration) { void GSAIFlee::_calculate_steering(Ref<GSAITargetAcceleration> acceleration) {
acceleration.linear = ((agent.position - target.position).normalized() * agent.linear_acceleration_max); ERR_FAIL_COND(!agent.is_valid());
acceleration.angular = 0; ERR_FAIL_COND(!target.is_valid());
}
acceleration->set_linear((agent->get_position() - target->get_position()).normalized() * agent->get_linear_acceleration_max());
acceleration->set_angular(0);
} }
GSAIFlee::GSAIFlee() { GSAIFlee::GSAIFlee() {
@ -16,6 +19,5 @@ GSAIFlee::GSAIFlee() {
GSAIFlee::~GSAIFlee() { GSAIFlee::~GSAIFlee() {
} }
static void GSAIFlee::_bind_methods() { void GSAIFlee::_bind_methods() {
ClassDB::bind_method(D_METHOD("_calculate_steering", "acceleration"), &GSAIFlee::_calculate_steering);
} }

View File

@ -1,11 +1,17 @@
#ifndef GSAI_FLEE_H #ifndef GSAI_FLEE_H
#define GSAI_FLEE_H #define GSAI_FLEE_H
#include "core/object/reference.h"
#include "gsai_seek.h"
class GSAITargetAcceleration;
class GSAIFlee : public GSAISeek { class GSAIFlee : public GSAISeek {
GDCLASS(GSAIFlee, GSAISeek); GDCLASS(GSAIFlee, GSAISeek);
public: public:
void _calculate_steering(const GSAITargetAcceleration &acceleration); void _calculate_steering(Ref<GSAITargetAcceleration> acceleration);
GSAIFlee(); GSAIFlee();
~GSAIFlee(); ~GSAIFlee();