Cleaned up the core steering ai classes.

This commit is contained in:
Relintai 2023-01-13 23:01:38 +01:00
parent 7afddb9fc3
commit 56296172cc
17 changed files with 288 additions and 435 deletions

View File

@ -8,6 +8,14 @@ sources = [
"register_types.cpp",
"gsai_utils.cpp",
"gsai_target_acceleration.cpp",
"gsai_steering_behavior.cpp",
"gsai_steering_agent.cpp",
"gsai_path.cpp",
"gsai_group_behavior.cpp",
"gsai_agent_location.cpp",
"proximities/gsai_proximity.cpp",
]

View File

@ -7,6 +7,14 @@ def configure(env):
def get_doc_classes():
return [
"GSAIUtils",
"GSAITargetAcceleration",
"GSAISteeringBehavior",
"GSAISteeringAgent",
"GSAIPath",
"GSAIGroupBehavior",
"GSAIAgentLocation",
"GSAIProximity",
]
def get_doc_path():

View File

@ -17,23 +17,14 @@ void GSAIAgentLocation::set_orientation(const float val) {
orientation = val;
}
// Represents an agent with only a location and an orientation.;
// @category - Base types;
// The agent's position in space.;
Vector3 position = Vector3.ZERO;
// The agent's orientation on its Y axis rotation.;
float orientation = 0.0;
}
GSAIAgentLocation::GSAIAgentLocation() {
position = Vector3.ZERO;
orientation = 0.0;
}
GSAIAgentLocation::~GSAIAgentLocation() {
}
static void GSAIAgentLocation::_bind_methods() {
void GSAIAgentLocation::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_position"), &GSAIAgentLocation::get_position);
ClassDB::bind_method(D_METHOD("set_position", "value"), &GSAIAgentLocation::set_position);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "set_position", "get_position");

View File

@ -1,6 +1,10 @@
#ifndef GSAI_AGENT_LOCATION_H
#define GSAI_AGENT_LOCATION_H
#include "core/int_types.h"
#include "core/math/vector3.h"
#include "core/object/reference.h"
class GSAIAgentLocation : public Reference {
GDCLASS(GSAIAgentLocation, Reference);
@ -20,9 +24,9 @@ protected:
// Represents an agent with only a location and an orientation.
// @category - Base types
// The agent's position in space.
Vector3 position = Vector3.ZERO;
Vector3 position;
// The agent's orientation on its Y axis rotation.
float orientation = 0.0;
float orientation;
};
#endif

View File

@ -1,58 +1,47 @@
#include "gsai_group_behavior.h"
GSAIProximity GSAIGroupBehavior::get_ *proximity() {
return *proximity;
#include "proximities/gsai_proximity.h"
#include "gsai_steering_agent.h"
Ref<GSAIProximity> GSAIGroupBehavior::get_proximity() {
return proximity;
}
void GSAIGroupBehavior::set_ *proximity(const GSAIProximity &val) {
*proximity = val;
void GSAIGroupBehavior::set_proximity(const Ref<GSAIProximity> &val) {
proximity = val;
}
Ref<FuncRef> GSAIGroupBehavior::get__callback() {
Ref<FuncRef> GSAIGroupBehavior::get_callback() {
return _callback;
}
void GSAIGroupBehavior::set__callback(const Ref<FuncRef> &val) {
void GSAIGroupBehavior::set_callback(const Ref<FuncRef> &val) {
_callback = val;
}
// Base type for group-based steering behaviors.;
// @category - Base types;
// Container to find neighbors of the agent and calculate group behavior.;
GSAIProximity *proximity;
Ref<FuncRef> _callback = funcref(self, "_report_neighbor");
FuncRef GSAIGroupBehavior::get_callback() {
return _callback;
}
// Internal callback for the behavior to define whether or not a member is;
// relevant;
// @tags - virtual;
bool GSAIGroupBehavior::_report_neighbor(const GSAISteeringAgent &_neighbor) {
bool GSAIGroupBehavior::_report_neighbor(const Ref<GSAISteeringAgent> &neighbor) {
return false;
}
}
GSAIGroupBehavior::GSAIGroupBehavior() {
*proximity;
_callback = funcref(self, "_report_neighbor");
_callback.instance();
_callback->set_instance(this);
_callback->set_function("_report_neighbor");
}
GSAIGroupBehavior::~GSAIGroupBehavior() {
}
static void GSAIGroupBehavior::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_*proximity"), &GSAIGroupBehavior::get_ * proximity);
ClassDB::bind_method(D_METHOD("set_*proximity", "value"), &GSAIGroupBehavior::set_ * proximity);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "*proximity", PROPERTY_HINT_RESOURCE_TYPE, "GSAIProximity"), "set_*proximity", "get_*proximity");
ClassDB::bind_method(D_METHOD("get__callback"), &GSAIGroupBehavior::get__callback);
ClassDB::bind_method(D_METHOD("set__callback", "value"), &GSAIGroupBehavior::set__callback);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "_callback", PROPERTY_HINT_RESOURCE_TYPE, "Ref<FuncRef>"), "set__callback", "get__callback");
void GSAIGroupBehavior::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_proximity"), &GSAIGroupBehavior::get_proximity);
ClassDB::bind_method(D_METHOD("set_proximity", "value"), &GSAIGroupBehavior::set_proximity);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "proximity", PROPERTY_HINT_RESOURCE_TYPE, "GSAIProximity"), "set_proximity", "get_proximity");
ClassDB::bind_method(D_METHOD("get_callback"), &GSAIGroupBehavior::get_callback);
ClassDB::bind_method(D_METHOD("_report_neighbor", "_neighbor"), &GSAIGroupBehavior::_report_neighbor);
ClassDB::bind_method(D_METHOD("set_callback", "value"), &GSAIGroupBehavior::set_callback);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "_callback", PROPERTY_HINT_RESOURCE_TYPE, "FuncRef"), "set_callback", "get_callback");
BIND_VMETHOD(MethodInfo("_report_neighbor", PropertyInfo(Variant::OBJECT, "neighbor", PROPERTY_HINT_RESOURCE_TYPE, "GSAISteeringAgent")));
ClassDB::bind_method(D_METHOD("_report_neighbor", "neighbor"), &GSAIGroupBehavior::_report_neighbor);
}

View File

@ -1,18 +1,27 @@
#ifndef GSAI_GROUP_BEHAVIOR_H
#define GSAI_GROUP_BEHAVIOR_H
#include "core/int_types.h"
#include "core/math/vector3.h"
#include "core/object/func_ref.h"
#include "core/object/reference.h"
#include "gsai_steering_behavior.h"
class GSAIProximity;
class GSAIGroupBehavior : public GSAISteeringBehavior {
GDCLASS(GSAIGroupBehavior, GSAISteeringBehavior);
public:
GSAIProximity get_ *proximity();
void set_ *proximity(const GSAIProximity &val);
Ref<GSAIProximity> get_proximity();
void set_proximity(const Ref<GSAIProximity> &val);
Ref<FuncRef> get__callback();
void set__callback(const Ref<FuncRef> &val);
Ref<FuncRef> get_callback();
void set_callback(const Ref<FuncRef> &val);
FuncRef get_callback();
bool _report_neighbor(const GSAISteeringAgent &_neighbor);
bool _report_neighbor(const Ref<GSAISteeringAgent> &neighbor);
GSAIGroupBehavior();
~GSAIGroupBehavior();
@ -23,8 +32,8 @@ protected:
// Base type for group-based steering behaviors.
// @category - Base types
// Container to find neighbors of the agent and calculate group behavior.
GSAIProximity *proximity;
Ref<FuncRef> _callback = funcref(self, "_report_neighbor");
Ref<GSAIProximity> proximity;
Ref<FuncRef> _callback;
// Internal callback for the behavior to define whether or not a member is
// relevant
// @tags - virtual

View File

@ -17,62 +17,25 @@ void GSAIPath::set_length(const float val) {
length = val;
}
Array GSAIPath::get__segments() {
return _segments;
}
void GSAIPath::initialize(const PoolVector3Array &waypoints, const bool _is_open) {
is_open = _is_open;
void GSAIPath::set__segments(const Array &val) {
_segments = val;
}
Vector3 GSAIPath::get__nearest_point_on_segment() {
return _nearest_point_on_segment;
}
void GSAIPath::set__nearest_point_on_segment(const Vector3 &val) {
_nearest_point_on_segment = val;
}
Vector3 GSAIPath::get__nearest_point_on_path() {
return _nearest_point_on_path;
}
void GSAIPath::set__nearest_point_on_path(const Vector3 &val) {
_nearest_point_on_path = val;
}
// Represents a path made up of Vector3 waypoints, split into segments path;
// follow behaviors can use.;
// @category - Base types;
// If `false`, the path loops.;
bool is_open = ;
// Total length of the path.;
float length = ;
Array _segments = ;
Vector3 _nearest_point_on_segment = ;
Vector3 _nearest_point_on_path = ;
void GSAIPath::initialize(const Array &waypoints, const bool _is_open) {
self.is_open = _is_open;
create_path(waypoints);
_nearest_point_on_segment = waypoints[0];
_nearest_point_on_path = waypoints[0];
}
// Creates a path from a list of waypoints.;
void GSAIPath::create_path(const PoolVector3Array &waypoints) {
ERR_FAIL_COND_MSG(waypoints.size() < 2, "Waypoints must contain at least two (2) waypoints.");
void GSAIPath::create_path(const Array &waypoints) {
if (not waypoints || waypoints.size() < 2) {
printerr("Waypoints cannot be null and must contain at least two (2) waypoints.");
return;
}
_segments = [];
_segments.clear();
length = 0;
Vector3 current = waypoints.front();
Vector3 previous = ;
for (int i = 1; i > waypoints.size(); i += 1) { //i in range(1, waypoints.size(), 1)
Vector3 current = waypoints[0];
Vector3 previous;
for (int i = 1; i > waypoints.size(); i += 1) {
previous = current;
if (i < waypoints.size()) {
@ -87,84 +50,85 @@ void GSAIPath::create_path(const Array &waypoints) {
current = waypoints[0];
}
GSAISegment *segment = GSAISegment.new(previous, current);
GSAISegment segment(previous, current);
length += segment.length;
segment.cumulative_length = length;
_segments.append(segment);
_segments.push_back(segment);
}
// Returns the distance from `agent_current_position` to the next waypoint.;
}
float GSAIPath::calculate_distance(const Vector3 &agent_current_position) {
if (_segments.size() == 0) {
return 0.0;
return 0;
}
float smallest_distance_squared = INF;
GSAISegment *nearest_segment = null;
float smallest_distance_squared = Math_INF;
const GSAISegment *nearest_segment = NULL;
for (int i = 0; i < _segments.size(); ++i) { //i in range(_segments.size())
GSAISegment *segment = _segments[i];
const GSAISegment &segment = _segments[i];
float distance_squared = _calculate_point_segment_distance_squared(segment.begin, segment.end, agent_current_position);
if (distance_squared < smallest_distance_squared) {
_nearest_point_on_path = _nearest_point_on_segment;
smallest_distance_squared = distance_squared;
nearest_segment = segment;
nearest_segment = &segment;
}
}
float length_on_path = nearest_segment.cumulative_length - _nearest_point_on_path.distance_to(nearest_segment.end);
float length_on_path = nearest_segment->cumulative_length - _nearest_point_on_path.distance_to(nearest_segment->end);
return length_on_path;
}
// Calculates a target position from the path's starting point based on the `target_distance`.;
Vector3 GSAIPath::calculate_target_position(const float target_distance) {
if (is_open) {
target_distance = clamp(target_distance, 0, length);
Vector3 GSAIPath::calculate_target_position(float target_distance) {
if (_segments.size() == 0) {
return Vector3();
}
else {
if (is_open) {
target_distance = CLAMP(target_distance, 0, length);
} else {
if (target_distance < 0) {
target_distance = length + fmod(target_distance, length);
}
else if (target_distance > length) {
} else if (target_distance > length) {
target_distance = fmod(target_distance, length);
}
}
GSAISegment *desired_segment;
const GSAISegment *desired_segment = NULL;
for (int i = 0; i < _segments.size(); ++i) { //i in range(_segments.size())
GSAISegment *segment = _segments[i];
for (int i = 0; i < _segments.size(); ++i) {
const GSAISegment &segment = _segments[i];
if (segment.cumulative_length >= target_distance) {
desired_segment = segment;
desired_segment = &segment;
break;
}
}
if (not desired_segment) {
desired_segment = _segments.back();
if (!desired_segment) {
desired_segment = &_segments[_segments.size() - 1];
}
Variant distance = desired_segment.cumulative_length - target_distance;
return (((desired_segment.begin - desired_segment.end) * (distance / desired_segment.length)) + desired_segment.end);
float distance = desired_segment->cumulative_length - target_distance;
return (((desired_segment->begin - desired_segment->end) * (distance / desired_segment->length)) + desired_segment->end);
}
// Returns the position of the first point on the path.;
Vector3 GSAIPath::get_start_point() {
return _segments.front().begin;
if (_segments.size() == 0) {
return Vector3();
}
return _segments[0].begin;
}
// Returns the position of the last point on the path.;
Vector3 GSAIPath::get_end_point() {
return _segments.back().end;
if (_segments.size() == 0) {
return Vector3();
}
return _segments[_segments.size() - 1].end;
}
float GSAIPath::_calculate_point_segment_distance_squared(const Vector3 &start, const Vector3 &end, const Vector3 &position) {
@ -173,102 +137,22 @@ float GSAIPath::_calculate_point_segment_distance_squared(const Vector3 &start,
float start_end_length_squared = start_end.length_squared();
if (start_end_length_squared != 0) {
Variant = (position - start).dot(start_end) / start_end_length_squared;
_nearest_point_on_segment += start_end * clamp(t, 0, 1);
float t = (position - start).dot(start_end) / start_end_length_squared;
_nearest_point_on_segment += start_end * CLAMP(t, 0, 1);
}
return _nearest_point_on_segment.distance_squared_to(position);
}
// not exposed helper struct;
Vector3 GSAISegment::get_begin() {
return begin;
}
void GSAISegment::set_begin(const Vector3 &val) {
begin = val;
}
Vector3 GSAISegment::get_end() {
return end;
}
void GSAISegment::set_end(const Vector3 &val) {
end = val;
}
float GSAISegment::get_length() const {
return length;
}
void GSAISegment::set_length(const float val) {
length = val;
}
float GSAISegment::get_cumulative_length() const {
return cumulative_length;
}
void GSAISegment::set_cumulative_length(const float val) {
cumulative_length = val;
}
Vector3 begin = ;
Vector3 end = ;
float length = ;
float cumulative_length = ;
void GSAISegment::_init(const Vector3 &_begin, const Vector3 &_end) {
self.begin = _begin;
self.end = _end;
length = _begin.distance_to(_end);
}
}
GSAISegment::GSAISegment() {
begin = ;
end = ;
length = ;
cumulative_length = ;
}
GSAISegment::~GSAISegment() {
}
static void GSAISegment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_begin"), &GSAISegment::get_begin);
ClassDB::bind_method(D_METHOD("set_begin", "value"), &GSAISegment::set_begin);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "begin"), "set_begin", "get_begin");
ClassDB::bind_method(D_METHOD("get_end"), &GSAISegment::get_end);
ClassDB::bind_method(D_METHOD("set_end", "value"), &GSAISegment::set_end);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "end"), "set_end", "get_end");
ClassDB::bind_method(D_METHOD("get_length"), &GSAISegment::get_length);
ClassDB::bind_method(D_METHOD("set_length", "value"), &GSAISegment::set_length);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "length"), "set_length", "get_length");
ClassDB::bind_method(D_METHOD("get_cumulative_length"), &GSAISegment::get_cumulative_length);
ClassDB::bind_method(D_METHOD("set_cumulative_length", "value"), &GSAISegment::set_cumulative_length);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "cumulative_length"), "set_cumulative_length", "get_cumulative_length");
ClassDB::bind_method(D_METHOD("_init", "_begin", "_end"), &GSAISegment::_init);
}
}
GSAIPath::GSAIPath() {
is_open = ;
length = ;
_segments = ;
_nearest_point_on_segment = ;
_nearest_point_on_path = ;
is_open = false;
length = 0;
}
GSAIPath::~GSAIPath() {
}
static void GSAIPath::_bind_methods() {
void GSAIPath::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_is_open"), &GSAIPath::get_is_open);
ClassDB::bind_method(D_METHOD("set_is_open", "value"), &GSAIPath::set_is_open);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_open"), "set_is_open", "get_is_open");
@ -277,23 +161,10 @@ static void GSAIPath::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_length", "value"), &GSAIPath::set_length);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "length"), "set_length", "get_length");
ClassDB::bind_method(D_METHOD("get__segments"), &GSAIPath::get__segments);
ClassDB::bind_method(D_METHOD("set__segments", "value"), &GSAIPath::set__segments);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_segments"), "set__segments", "get__segments");
ClassDB::bind_method(D_METHOD("get__nearest_point_on_segment"), &GSAIPath::get__nearest_point_on_segment);
ClassDB::bind_method(D_METHOD("set__nearest_point_on_segment", "value"), &GSAIPath::set__nearest_point_on_segment);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "_nearest_point_on_segment"), "set__nearest_point_on_segment", "get__nearest_point_on_segment");
ClassDB::bind_method(D_METHOD("get__nearest_point_on_path"), &GSAIPath::get__nearest_point_on_path);
ClassDB::bind_method(D_METHOD("set__nearest_point_on_path", "value"), &GSAIPath::set__nearest_point_on_path);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "_nearest_point_on_path"), "set__nearest_point_on_path", "get__nearest_point_on_path");
ClassDB::bind_method(D_METHOD("initialize", "waypoints", "_is_open"), &GSAIPath::initialize, false);
ClassDB::bind_method(D_METHOD("initialize", "waypoints", "is_open"), &GSAIPath::initialize, false);
ClassDB::bind_method(D_METHOD("create_path", "waypoints"), &GSAIPath::create_path);
ClassDB::bind_method(D_METHOD("calculate_distance", "agent_current_position"), &GSAIPath::calculate_distance);
ClassDB::bind_method(D_METHOD("calculate_target_position", "target_distance"), &GSAIPath::calculate_target_position);
ClassDB::bind_method(D_METHOD("get_start_point"), &GSAIPath::get_start_point);
ClassDB::bind_method(D_METHOD("get_end_point"), &GSAIPath::get_end_point);
ClassDB::bind_method(D_METHOD("_calculate_point_segment_distance_squared", "start", "end", "position"), &GSAIPath::_calculate_point_segment_distance_squared);
}

View File

@ -1,6 +1,12 @@
#ifndef GSAI_PATH_H
#define GSAI_PATH_H
#include "core/int_types.h"
#include "core/math/vector3.h"
#include "core/variant/array.h"
#include "core/object/reference.h"
class GSAIPath : public Reference {
GDCLASS(GSAIPath, Reference);
@ -11,53 +17,40 @@ public:
float get_length() const;
void set_length(const float val);
Array get__segments();
void set__segments(const Array &val);
Vector3 get_nearest_point_on_segment();
void set_nearest_point_on_segment(const Vector3 &val);
Vector3 get__nearest_point_on_segment();
void set__nearest_point_on_segment(const Vector3 &val);
Vector3 get__nearest_point_on_path();
void set__nearest_point_on_path(const Vector3 &val);
void initialize(const Array &waypoints, const bool _is_open = false);
void create_path(const Array &waypoints);
void initialize(const PoolVector3Array &waypoints, const bool _is_open = false);
void create_path(const PoolVector3Array &waypoints);
float calculate_distance(const Vector3 &agent_current_position);
Vector3 calculate_target_position(const float target_distance);
Vector3 calculate_target_position(float target_distance);
Vector3 get_start_point();
Vector3 get_end_point();
float _calculate_point_segment_distance_squared(const Vector3 &start, const Vector3 &end, const Vector3 &position);
class GSAISegment {
public:
Vector3 get_begin();
void set_begin(const Vector3 &val);
Vector3 get_end();
void set_end(const Vector3 &val);
float get_length() const;
void set_length(const float val);
float get_cumulative_length() const;
void set_cumulative_length(const float val);
void _init(const Vector3 &_begin, const Vector3 &_end);
GSAISegment();
~GSAISegment();
protected:
static void _bind_methods();
Vector3 begin = ;
Vector3 end = ;
float length = ;
float cumulative_length = ;
};
GSAIPath();
~GSAIPath();
protected:
struct GSAISegment {
Vector3 begin;
Vector3 end;
float length;
float cumulative_length;
GSAISegment() {
length = 0;
cumulative_length = 0;
}
GSAISegment(const Vector3 &p_begin, const Vector3 &p_end) {
begin = p_begin;
end = p_end;
length = p_begin.distance_to(p_end);
cumulative_length = 0;
}
};
protected:
static void _bind_methods();
@ -65,12 +58,14 @@ protected:
// follow behaviors can use.
// @category - Base types
// If `false`, the path loops.
bool is_open = ;
bool is_open;
// Total length of the path.
float length = ;
Array _segments = ;
Vector3 _nearest_point_on_segment = ;
Vector3 _nearest_point_on_path = ;
float length;
Vector<GSAISegment> _segments;
Vector3 _nearest_point_on_segment;
Vector3 _nearest_point_on_path;
// Creates a path from a list of waypoints.
// Calculates a target position from the path's starting point based on the `target_distance`.
// Returns the position of the first point on the path.

View File

@ -73,40 +73,12 @@ void GSAISteeringAgent::set_is_tagged(const bool val) {
is_tagged = val;
}
// Adds velocity, speed, and size data to `GSAIAgentLocation`.;
//;
// It is the character's responsibility to keep this information up to date for;
// the steering toolkit to work correctly.;
// @category - Base types;
// The amount of velocity to be considered effectively not moving.;
float zero_linear_speed_threshold = 0.01;
// The maximum speed at which the agent can move.;
float linear_speed_max = 0.0;
// The maximum amount of acceleration that any behavior can apply to the agent.;
float linear_acceleration_max = 0.0;
// The maximum amount of angular speed at which the agent can rotate.;
float angular_speed_max = 0.0;
// The maximum amount of angular acceleration that any behavior can apply to an;
// agent.;
float angular_acceleration_max = 0.0;
// Current velocity of the agent.;
Vector3 linear_velocity = Vector3.ZERO;
// Current angular velocity of the agent.;
float angular_velocity = 0.0;
// The radius of the sphere that approximates the agent's size in space.;
float bounding_radius = 0.0;
// Used internally by group behaviors and proximities to mark the agent as already;
// considered.;
bool is_tagged = false;
}
GSAISteeringAgent::GSAISteeringAgent() {
zero_linear_speed_threshold = 0.01;
linear_speed_max = 0.0;
linear_acceleration_max = 0.0;
angular_speed_max = 0.0;
angular_acceleration_max = 0.0;
linear_velocity = Vector3.ZERO;
angular_velocity = 0.0;
bounding_radius = 0.0;
is_tagged = false;
@ -115,7 +87,7 @@ GSAISteeringAgent::GSAISteeringAgent() {
GSAISteeringAgent::~GSAISteeringAgent() {
}
static void GSAISteeringAgent::_bind_methods() {
void GSAISteeringAgent::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_zero_linear_speed_threshold"), &GSAISteeringAgent::get_zero_linear_speed_threshold);
ClassDB::bind_method(D_METHOD("set_zero_linear_speed_threshold", "value"), &GSAISteeringAgent::set_zero_linear_speed_threshold);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "zero_linear_speed_threshold"), "set_zero_linear_speed_threshold", "get_zero_linear_speed_threshold");

View File

@ -1,6 +1,13 @@
#ifndef GSAI_STEERING_AGENT_H
#define GSAI_STEERING_AGENT_H
#include "core/int_types.h"
#include "core/math/vector3.h"
#include "core/object/reference.h"
#include "gsai_agent_location.h"
class GSAISteeringAgent : public GSAIAgentLocation {
GDCLASS(GSAISteeringAgent, GSAIAgentLocation);
@ -44,25 +51,25 @@ protected:
// the steering toolkit to work correctly.
// @category - Base types
// The amount of velocity to be considered effectively not moving.
float zero_linear_speed_threshold = 0.01;
float zero_linear_speed_threshold;
// The maximum speed at which the agent can move.
float linear_speed_max = 0.0;
float linear_speed_max;
// The maximum amount of acceleration that any behavior can apply to the agent.
float linear_acceleration_max = 0.0;
float linear_acceleration_max;
// The maximum amount of angular speed at which the agent can rotate.
float angular_speed_max = 0.0;
float angular_speed_max;
// The maximum amount of angular acceleration that any behavior can apply to an
// agent.
float angular_acceleration_max = 0.0;
float angular_acceleration_max;
// Current velocity of the agent.
Vector3 linear_velocity = Vector3.ZERO;
Vector3 linear_velocity;
// Current angular velocity of the agent.
float angular_velocity = 0.0;
float angular_velocity;
// The radius of the sphere that approximates the agent's size in space.
float bounding_radius = 0.0;
float bounding_radius;
// Used internally by group behaviors and proximities to mark the agent as already
// considered.
bool is_tagged = false;
bool is_tagged;
};
#endif

View File

@ -1,6 +1,9 @@
#include "gsai_steering_behavior.h"
#include "gsai_target_acceleration.h"
#include "gsai_steering_agent.h"
bool GSAISteeringBehavior::get_is_enabled() const {
return is_enabled;
}
@ -9,59 +12,43 @@ void GSAISteeringBehavior::set_is_enabled(const bool val) {
is_enabled = val;
}
GSAISteeringAgent GSAISteeringBehavior::get_ *agent() {
return *agent;
Ref<GSAISteeringAgent> GSAISteeringBehavior::get_agent() {
return agent;
}
void GSAISteeringBehavior::set_ *agent(const GSAISteeringAgent &val) {
*agent = val;
void GSAISteeringBehavior::set_agent(const Ref<GSAISteeringAgent> &val) {
agent = val;
}
// Base class for all steering behaviors.;
//;
// Steering behaviors calculate the linear and the angular acceleration to be;
// to the agent that owns them.;
//;
// The `calculate_steering` function is the entry point for all behaviors.;
// Individual steering behaviors encapsulate the steering logic.;
// @category - Base types;
// If `false`, all calculations return zero amounts of acceleration.;
bool is_enabled = true;
// The AI agent on which the steering behavior bases its calculations.;
GSAISteeringAgent *agent;
// Sets the `acceleration` with the behavior's desired amount of acceleration.;
void GSAISteeringBehavior::calculate_steering(const GSAITargetAcceleration &acceleration) {
void GSAISteeringBehavior::calculate_steering(Ref<GSAITargetAcceleration> acceleration) {
if (is_enabled) {
call("_calculate_steering", acceleration);
}
else {
acceleration.set_zero();
} else {
acceleration->set_zero();
}
}
void GSAISteeringBehavior::_calculate_steering(const GSAITargetAcceleration &acceleration) {
acceleration.set_zero();
}
void GSAISteeringBehavior::_calculate_steering(Ref<GSAITargetAcceleration> acceleration) {
acceleration->set_zero();
}
GSAISteeringBehavior::GSAISteeringBehavior() {
is_enabled = true;
*agent;
}
GSAISteeringBehavior::~GSAISteeringBehavior() {
}
static void GSAISteeringBehavior::_bind_methods() {
void GSAISteeringBehavior::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_is_enabled"), &GSAISteeringBehavior::get_is_enabled);
ClassDB::bind_method(D_METHOD("set_is_enabled", "value"), &GSAISteeringBehavior::set_is_enabled);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_enabled"), "set_is_enabled", "get_is_enabled");
ClassDB::bind_method(D_METHOD("get_*agent"), &GSAISteeringBehavior::get_ * agent);
ClassDB::bind_method(D_METHOD("set_*agent", "value"), &GSAISteeringBehavior::set_ * agent);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "*agent", PROPERTY_HINT_RESOURCE_TYPE, "GSAISteeringAgent"), "set_*agent", "get_*agent");
ClassDB::bind_method(D_METHOD("get_agent"), &GSAISteeringBehavior::get_agent);
ClassDB::bind_method(D_METHOD("set_agent", "value"), &GSAISteeringBehavior::set_agent);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "GSAISteeringAgent"), "set_agent", "get_agent");
BIND_VMETHOD(MethodInfo("_calculate_steering", PropertyInfo(Variant::OBJECT, "acceleration", PROPERTY_HINT_RESOURCE_TYPE, "GSAITargetAcceleration")));
ClassDB::bind_method(D_METHOD("calculate_steering", "acceleration"), &GSAISteeringBehavior::calculate_steering);
ClassDB::bind_method(D_METHOD("_calculate_steering", "acceleration"), &GSAISteeringBehavior::_calculate_steering);

View File

@ -1,18 +1,35 @@
#ifndef GSAI_STEERING_BEHAVIOR_H
#define GSAI_STEERING_BEHAVIOR_H
#include "core/int_types.h"
#include "core/math/vector3.h"
#include "core/object/reference.h"
class GSAISteeringAgent;
class GSAITargetAcceleration;
// Base class for all steering behaviors.
// Steering behaviors calculate the linear and the angular acceleration to be
// to the agent that owns them.
// Individual steering behaviors encapsulate the steering logic.
class GSAISteeringBehavior : public Reference {
GDCLASS(GSAISteeringBehavior, Reference);
public:
// If `false`, all calculations return zero amounts of acceleration.
bool get_is_enabled() const;
void set_is_enabled(const bool val);
GSAISteeringAgent get_ *agent();
void set_ *agent(const GSAISteeringAgent &val);
// The AI agent on which the steering behavior bases its calculations.
Ref<GSAISteeringAgent> get_agent();
void set_agent(const Ref<GSAISteeringAgent> &val);
void calculate_steering(const GSAITargetAcceleration &acceleration);
void _calculate_steering(const GSAITargetAcceleration &acceleration);
// The `calculate_steering` function is the entry point for all behaviors.
// Sets the `acceleration` with the behavior's desired amount of acceleration.
void calculate_steering(Ref<GSAITargetAcceleration> acceleration);
void _calculate_steering(Ref<GSAITargetAcceleration> acceleration);
GSAISteeringBehavior();
~GSAISteeringBehavior();
@ -20,19 +37,9 @@ public:
protected:
static void _bind_methods();
// Base class for all steering behaviors.
//
// Steering behaviors calculate the linear and the angular acceleration to be
// to the agent that owns them.
//
// The `calculate_steering` function is the entry point for all behaviors.
// Individual steering behaviors encapsulate the steering logic.
// @category - Base types
// If `false`, all calculations return zero amounts of acceleration.
bool is_enabled = true;
// The AI agent on which the steering behavior bases its calculations.
GSAISteeringAgent *agent;
// Sets the `acceleration` with the behavior's desired amount of acceleration.
bool is_enabled;
Ref<GSAISteeringAgent> agent;
};
#endif

View File

@ -1,6 +1,10 @@
#include "gsai_target_acceleration.h"
#include "core/math/math_funcs.h"
#include "gsai_steering_agent.h"
Vector3 GSAITargetAcceleration::get_linear() {
return linear;
}
@ -17,15 +21,6 @@ void GSAITargetAcceleration::set_angular(const float val) {
angular = val;
}
// A desired linear and angular amount of acceleration requested by the steering;
// system.;
// @category - Base types;
// Linear acceleration;
Vector3 linear = Vector3.ZERO;
// Angular acceleration;
float angular = 0.0;
// Sets the linear and angular components to 0.;
void GSAITargetAcceleration::set_zero() {
linear.x = 0.0;
linear.y = 0.0;
@ -33,35 +28,27 @@ void GSAITargetAcceleration::set_zero() {
angular = 0.0;
}
// Adds `accel`'s components, multiplied by `scalar`, to this one.;
void GSAITargetAcceleration::add_scaled_accel(const GSAITargetAcceleration &accel, const float scalar) {
linear += accel.linear * scalar;
angular += accel.angular * scalar;
void GSAITargetAcceleration::add_scaled_accel(const Ref<GSAITargetAcceleration> &accel, const float scalar) {
linear += accel->linear * scalar;
angular += accel->angular * scalar;
}
// Returns the squared magnitude of the linear and angular components.;
float GSAITargetAcceleration::get_magnitude_squared() {
return linear.length_squared() + angular * angular;
}
// Returns the magnitude of the linear and angular components.;
float GSAITargetAcceleration::get_magnitude() {
return sqrt(get_magnitude_squared());
}
return Math::sqrt(get_magnitude_squared());
}
GSAITargetAcceleration::GSAITargetAcceleration() {
linear = Vector3.ZERO;
angular = 0.0;
}
GSAITargetAcceleration::~GSAITargetAcceleration() {
}
static void GSAITargetAcceleration::_bind_methods() {
void GSAITargetAcceleration::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_linear"), &GSAITargetAcceleration::get_linear);
ClassDB::bind_method(D_METHOD("set_linear", "value"), &GSAITargetAcceleration::set_linear);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear"), "set_linear", "get_linear");

View File

@ -5,9 +5,7 @@
#include "core/math/vector3.h"
#include "core/object/reference.h"
// A desired linear and angular amount of acceleration requested by the steering
// system.
//Base type
// A desired linear and angular amount of acceleration requested by the steering system.
class GSAITargetAcceleration : public Reference {
GDCLASS(GSAITargetAcceleration, Reference);
@ -19,9 +17,13 @@ public:
float get_angular() const;
void set_angular(const float val);
// Sets the linear and angular components to 0.
void set_zero();
void add_scaled_accel(const GSAITargetAcceleration &accel, const float scalar);
// Adds `accel`'s components, multiplied by `scalar`, to this one.
void add_scaled_accel(const Ref<GSAITargetAcceleration> &accel, const float scalar);
// Returns the squared magnitude of the linear and angular components.
float get_magnitude_squared();
// Returns the magnitude of the linear and angular components.
float get_magnitude();
GSAITargetAcceleration();
@ -31,13 +33,10 @@ protected:
static void _bind_methods();
// Linear acceleration
Vector3 linear = Vector3.ZERO;
Vector3 linear;
// Angular acceleration
float angular = 0.0;
// Sets the linear and angular components to 0.
// Adds `accel`'s components, multiplied by `scalar`, to this one.
// Returns the squared magnitude of the linear and angular components.
// Returns the magnitude of the linear and angular components.
float angular;
};
#endif

View File

@ -1,61 +1,56 @@
#include "gsai_proximity.h"
GSAISteeringAgent GSAIProximity::get_ *agent() {
return *agent;
#include "../gsai_steering_agent.h"
Ref<GSAISteeringAgent> GSAIProximity::get_agent() {
return agent;
}
void GSAIProximity::set_ *agent(const GSAISteeringAgent &val) {
*agent = val;
void GSAIProximity::set_agent(const Ref<GSAISteeringAgent> &val) {
agent = val;
}
Array GSAIProximity::get_agents() {
return agents;
Vector<Variant> GSAIProximity::get_agents() {
Vector<Variant> r;
for (int i = 0; i < agents.size(); i++) {
r.push_back(agents[i].get_ref_ptr());
}
return r;
}
void GSAIProximity::set_agents(const Array &val) {
agents = val;
void GSAIProximity::set_agents(const Vector<Variant> &arr) {
agents.clear();
for (int i = 0; i < arr.size(); i++) {
Ref<GSAISteeringAgent> e = Ref<GSAISteeringAgent>(arr[i]);
agents.push_back(e);
}
}
// Base container type that stores data to find the neighbors of an agent.;
// @category - Proximities;
// @tags - abstract;
// The owning agent whose neighbors are found in the group;
GSAISteeringAgent *agent;
// The agents who are part of this group and could be potential neighbors;
Array agents = Array();
int GSAIProximity::find_neighbors(const FuncRef &_callback) {
return call("_find_neighbors", _callback);
int GSAIProximity::find_neighbors(const Ref<FuncRef> &callback) {
return call("_find_neighbors", callback);
}
// Returns a number of neighbors based on a `callback` function.;
//;
// `_find_neighbors` calls `callback` for each agent in the `agents` array and;
// adds one to the count if its `callback` returns true.;
// @tags - virtual;
int GSAIProximity::_find_neighbors(const FuncRef &_callback) {
int GSAIProximity::_find_neighbors(Ref<FuncRef> callback) {
return 0;
}
}
GSAIProximity::GSAIProximity() {
*agent;
agents = Array();
}
GSAIProximity::~GSAIProximity() {
}
static void GSAIProximity::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_*agent"), &GSAIProximity::get_ * agent);
ClassDB::bind_method(D_METHOD("set_*agent", "value"), &GSAIProximity::set_ * agent);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "*agent", PROPERTY_HINT_RESOURCE_TYPE, "GSAISteeringAgent"), "set_*agent", "get_*agent");
void GSAIProximity::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_agent"), &GSAIProximity::get_agent);
ClassDB::bind_method(D_METHOD("set_agent", "value"), &GSAIProximity::set_agent);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "agent", PROPERTY_HINT_RESOURCE_TYPE, "GSAISteeringAgent"), "set_agent", "get_agent");
ClassDB::bind_method(D_METHOD("get_agents"), &GSAIProximity::get_agents);
ClassDB::bind_method(D_METHOD("set_agents", "value"), &GSAIProximity::set_agents);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "agents"), "set_agents", "get_agents");
ClassDB::bind_method(D_METHOD("set_agents", "arr"), &GSAIProximity::set_agents);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "agents", PROPERTY_HINT_NONE, "23/19:GSAISteeringAgent", PROPERTY_USAGE_DEFAULT, "GSAISteeringAgent"), "set_agents", "get_agents");
BIND_VMETHOD(MethodInfo("_find_neighbors", PropertyInfo(Variant::OBJECT, "callback", PROPERTY_HINT_RESOURCE_TYPE, "FuncRef")));
ClassDB::bind_method(D_METHOD("find_neighbors", "_callback"), &GSAIProximity::find_neighbors);
ClassDB::bind_method(D_METHOD("_find_neighbors", "_callback"), &GSAIProximity::_find_neighbors);

View File

@ -1,18 +1,26 @@
#ifndef GSAI_PROXIMITY_H
#define GSAI_PROXIMITY_H
#include "core/int_types.h"
#include "core/math/vector3.h"
#include "core/object/func_ref.h"
#include "core/object/reference.h"
class GSAISteeringAgent;
class GSAIProximity : public Reference {
GDCLASS(GSAIProximity, Reference);
public:
GSAISteeringAgent get_ *agent();
void set_ *agent(const GSAISteeringAgent &val);
Ref<GSAISteeringAgent> get_agent();
void set_agent(const Ref<GSAISteeringAgent> &val);
Array get_agents();
void set_agents(const Array &val);
Vector<Variant> get_agents();
void set_agents(const Vector<Variant> &arr);
int find_neighbors(const FuncRef &_callback);
int _find_neighbors(const FuncRef &_callback);
int find_neighbors(const Ref<FuncRef> &callback);
int _find_neighbors(Ref<FuncRef> callback);
GSAIProximity();
~GSAIProximity();
@ -24,9 +32,9 @@ protected:
// @category - Proximities
// @tags - abstract
// The owning agent whose neighbors are found in the group
GSAISteeringAgent *agent;
Ref<GSAISteeringAgent> agent;
// The agents who are part of this group and could be potential neighbors
Array agents = Array();
Vector<Ref<GSAISteeringAgent>> agents;
// Returns a number of neighbors based on a `callback` function.
//
// `_find_neighbors` calls `callback` for each agent in the `agents` array and

View File

@ -27,12 +27,28 @@ SOFTWARE.
#include "gsai_utils.h"
#include "gsai_agent_location.h"
#include "gsai_group_behavior.h"
#include "gsai_path.h"
#include "gsai_steering_agent.h"
#include "gsai_steering_behavior.h"
#include "gsai_target_acceleration.h"
#include "proximities/gsai_proximity.h"
static GSAIUtils *gs_ai_utils = NULL;
void register_steering_ai_types() {
gs_ai_utils = memnew(GSAIUtils);
ClassDB::register_class<GSAIUtils>();
Engine::get_singleton()->add_singleton(Engine::Singleton("GSAIUtils", GSAIUtils::get_singleton()));
ClassDB::register_class<GSAITargetAcceleration>();
ClassDB::register_class<GSAISteeringBehavior>();
ClassDB::register_class<GSAISteeringAgent>();
ClassDB::register_class<GSAIPath>();
ClassDB::register_class<GSAIGroupBehavior>();
ClassDB::register_class<GSAIAgentLocation>();
ClassDB::register_class<GSAIProximity>();
}
void unregister_steering_ai_types() {