Update code reference

Proof and edit docstrings in all the base types and proximity types
Remove docstring for the _init builtin callback
This commit is contained in:
Nathan Lovato 2020-01-27 17:31:10 -06:00
parent 2d8bdaebd7
commit 6276fc0413
23 changed files with 114 additions and 142 deletions

View File

@ -14,7 +14,6 @@ var deceleration_radius: float
var time_to_reach := 0.1
# Initializes the behavior
func _init(agent: GSTSteeringAgent, target: GSTAgentLocation).(agent) -> void:
self.target = target
@ -22,22 +21,22 @@ func _init(agent: GSTSteeringAgent, target: GSTAgentLocation).(agent) -> void:
func _arrive(acceleration: GSTTargetAcceleration, target_position: Vector3) -> GSTTargetAcceleration:
var to_target := target_position - agent.position
var distance := to_target.length()
if distance <= arrival_tolerance:
acceleration.set_zero()
else:
var desired_speed := agent.linear_speed_max
if distance <= deceleration_radius:
desired_speed *= distance / deceleration_radius
var desired_velocity := to_target * desired_speed/distance
desired_velocity = (desired_velocity - agent.linear_velocity) * 1.0 / time_to_reach
acceleration.linear = GSTUtils.clampedv3(desired_velocity, agent.linear_acceleration_max)
acceleration.angular = 0
return acceleration

View File

@ -11,7 +11,6 @@ var first_relative_position: Vector3
var first_relative_velocity: Vector3
# Intializes the behavior
func _init(agent: GSTSteeringAgent, proximity: GSTProximity).(agent, proximity) -> void:
pass

View File

@ -13,7 +13,6 @@ var _behaviors := []
var _accel := GSTTargetAcceleration.new()
# Initializes the behavior
func _init(agent: GSTSteeringAgent).(agent) -> void:
pass

View File

@ -7,7 +7,6 @@ extends GSTGroupBehavior
var center_of_mass: Vector3
# Initializes the behavior
func _init(agent: GSTSteeringAgent, proximity: GSTProximity).(agent, proximity) -> void:
pass

View File

@ -3,7 +3,6 @@ extends GSTPursue
# Calculates acceleration to take an agent away from where a target agent will be.
# Initializes the behavior
func _init(
agent: GSTSteeringAgent,
target: GSTSteeringAgent,

View File

@ -4,7 +4,6 @@ extends GSTMatchOrientation
# The acceleration will attempt to arrive with zero remaining angular velocity.
# Initializes the behavior
func _init(agent: GSTSteeringAgent, target: GSTAgentLocation).(agent, target) -> void:
pass

View File

@ -3,7 +3,6 @@ extends GSTSeek
# Calculates acceleration to take an agent directly away from a target agent.
# Initializes the behavior
func _init(agent: GSTSteeringAgent, target: GSTAgentLocation).(agent, target) -> void:
pass

View File

@ -15,7 +15,6 @@ var arrive_enabled := true
var prediction_time := 0.0
# Initializes the behavior
func _init(
agent: GSTSteeringAgent,
path: GSTPath,

View File

@ -3,7 +3,6 @@ extends GSTMatchOrientation
# Calculates an angular acceleration to match an agent's orientation to its direction of travel.
# Initializes the behavior
func _init(agent: GSTSteeringAgent).(agent, null) -> void:
pass

View File

@ -14,7 +14,6 @@ var deceleration_radius: float
var time_to_reach: float = 0.1
# Initializes the behavior
func _init(agent: GSTSteeringAgent, target: GSTAgentLocation).(agent) -> void:
self.target = target

View File

@ -11,7 +11,6 @@ var last_selected_index: int
var zero_threshold: float
# Initializes the behavior
func _init(agent: GSTSteeringAgent, zero_threshold := 0.001).(agent) -> void:
self.zero_threshold = zero_threshold

View File

@ -10,7 +10,6 @@ var target: GSTSteeringAgent
var predict_time_max: float
# Initializes the behavior
func _init(
agent: GSTSteeringAgent,
target: GSTSteeringAgent,

View File

@ -7,7 +7,6 @@ extends GSTSteeringBehavior
var target: GSTAgentLocation
# Initializes the behavior
func _init(agent: GSTSteeringAgent, target: GSTAgentLocation).(agent) -> void:
self.target = target

View File

@ -13,7 +13,6 @@ var decay_coefficient := 1.0
var acceleration: GSTTargetAcceleration
# Initializes the behavior
func _init(agent: GSTSteeringAgent, proximity: GSTProximity).(agent, proximity) -> void:
pass

View File

@ -1,5 +1,5 @@
class_name GSTAgentLocation
# Data type to represent an agent with a location and an orientation only.
# Represents an agent with only a location and an orientation.
# The agent's position in space.

View File

@ -1,19 +1,19 @@
extends GSTSteeringBehavior
class_name GSTGroupBehavior
# Extended behavior that features a Proximity group for group-based behaviors.
# Base type for group-based steering behaviors.
# The group area definition that will be used to find the owning agent's neighbors
# Container to find neighbors of the agent and apply a group behavior.
var proximity: GSTProximity
var _callback := funcref(self, "report_neighbor")
# Initializes the behavior
func _init(agent: GSTSteeringAgent, proximity: GSTProximity).(agent) -> void:
self.proximity = proximity
# Internal callback for the behavior to define whether or not a member is relevant
# Internal callback for the behavior to define whether or not a member is
# relevant
func report_neighbor(neighbor: GSTSteeringAgent) -> bool:
return false

View File

@ -1,136 +1,110 @@
extends Reference
class_name GSTPath
# Represents a path made up of Vector3 waypoints, split into path segments for use by path
# following behaviors.
extends Reference class_name GSTPath
# Represents a path made up of Vector3 waypoints, split into segments path
# follow behaviors can use.
# Whether the path is a loop, or has its start and end disconnected and open ended
# If `false`, the path loops.
var open: bool
# The length of the full path
# Total length of the path.
var length: float
var _segments: Array
var _nearest_point_on_segment: Vector3
var _nearest_point_on_path: Vector3
var _nearest_point_on_segment: Vector3 var _nearest_point_on_path: Vector3
# Initializes and creates a path with the provided waypoints
func _init(waypoints: Array, open := false) -> void:
self.open = open
create_path(waypoints)
_nearest_point_on_segment = waypoints[0]
_nearest_point_on_path = waypoints[0]
self.open = open create_path(waypoints) _nearest_point_on_segment =
waypoints[0] _nearest_point_on_path = waypoints[0]
# Creates a path with the provided waypoints
# Creates a path from a list of waypoints.
func create_path(waypoints: Array) -> void:
if not waypoints or waypoints.size() < 2:
printerr("Waypoints cannot be null and must contain at least two (2) waypoints.")
return
_segments = []
length = 0
var current: Vector3 = waypoints.front()
var previous: Vector3
printerr("Waypoints cannot be null and must contain at least two (2)
waypoints.") return
_segments = [] length = 0 var current: Vector3 = waypoints.front() var
previous: Vector3
for i in range(1, waypoints.size(), 1):
previous = current
if i < waypoints.size():
current = waypoints[i]
elif open:
break
else:
current = waypoints[0]
var segment := GSTSegment.new(previous, current)
length += segment.length
segment.cumulative_length = length
previous = current if i < waypoints.size():
current = waypoints[i] elif open:
break else:
current = waypoints[0] var segment := GSTSegment.new(previous,
current) length += segment.length segment.cumulative_length = length
_segments.append(segment)
# Returns the distance from the provided `agent_current_position` to the next point waypoint.
# Returns the distance from `agent_current_position` to the next waypoint.
func calculate_distance(agent_current_position: Vector3) -> float:
if _segments.size() == 0:
return 0.0
var smallest_distance_squared: float = INF
var nearest_segment: GSTSegment
for i in range(_segments.size()):
var segment: GSTSegment = _segments[i]
var distance_squared := _calculate_point_segment_distance_squared(
segment.begin,
segment.end,
agent_current_position
return 0.0 var smallest_distance_squared: float = INF var
nearest_segment: GSTSegment for i in range(_segments.size()):
var segment: GSTSegment = _segments[i] var 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
smallest_distance_squared = distance_squared nearest_segment =
segment
var length_on_path := (
nearest_segment.cumulative_length -
nearest_segment.cumulative_length -
_nearest_point_on_path.distance_to(nearest_segment.end))
return length_on_path
# Calculates the target position on the path based on the provided `target_distance` from the
# path's starting point.
# Calculates a target position from the path's starting point based on the `target_distance`.
func calculate_target_position(target_distance: float) -> Vector3:
if open:
target_distance = clamp(target_distance, 0, length)
else:
target_distance = clamp(target_distance, 0, length) else:
if target_distance < 0:
target_distance = length + fmod(target_distance, length)
elif target_distance > length:
target_distance = length + fmod(target_distance, length) elif
target_distance > length:
target_distance = fmod(target_distance, length)
var desired_segment: GSTSegment
for i in range(_segments.size()):
var segment: GSTSegment = _segments[i]
if segment.cumulative_length >= target_distance:
desired_segment = segment
break
var desired_segment: GSTSegment for i in range(_segments.size()):
var segment: GSTSegment = _segments[i] if segment.cumulative_length >=
target_distance:
desired_segment = segment break
if not desired_segment:
desired_segment = _segments.back()
var distance := desired_segment.cumulative_length - target_distance
return (
(desired_segment.begin - desired_segment.end) *
(distance / desired_segment.length) + desired_segment.end)
(desired_segment.begin - desired_segment.end) * (distance /
desired_segment.length) + desired_segment.end)
# Returns the position of the beginning point of the path
# Returns the position of the first point on the path.
func get_start_point() -> Vector3:
return _segments.front().begin
# Returns the position of the last point of the path
# Returns the position of the last point on the path.
func get_end_point() -> Vector3:
return _segments.back().end
func _calculate_point_segment_distance_squared(start: Vector3, end: Vector3, position: Vector3) -> float:
_nearest_point_on_segment = start
var start_end := end - start
var start_end_length_squared := start_end.length_squared()
if start_end_length_squared != 0:
func _calculate_point_segment_distance_squared(start: Vector3, end: Vector3,
position: Vector3) -> float:
_nearest_point_on_segment = start var start_end := end - start var
start_end_length_squared := start_end.length_squared() if
start_end_length_squared != 0:
var 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)
class GSTSegment:
var begin: Vector3
var end: Vector3
var length: float
var cumulative_length: float
var begin: Vector3 var end: Vector3 var length: float var cumulative_length:
float
func _init(begin: Vector3, end: Vector3) -> void:
self.begin = begin
self.end = end
length = begin.distance_to(end)
self.begin = begin self.end = end length = begin.distance_to(end)

View File

@ -1,24 +1,28 @@
extends GSTAgentLocation
class_name GSTSteeringAgent
# An extended `GSTAgentLocation` that adds velocity, speed, and size data. It is the character's
# responsibility to keep this information up to date for the steering toolkit to work correctly.
# Adds velocity, speed, and size data to `GSTAgentLocation`.
#
# It is the character's responsibility to keep this information up to date for
# the steering toolkit to work correctly.
# The amount of velocity to be considered effectively not moving.
var zero_linear_speed_threshold := 0.01
# The maximum amount of speed the agent can move at.
# The maximum speed at which the agent can move.
var linear_speed_max := 0.0
# The maximum amount of acceleration that any behavior can apply to an agent.
# The maximum amount of acceleration that any behavior can apply to the agent.
var linear_acceleration_max := 0.0
# The maximum amount of angular speed the agent can rotate at.
# The maximum amount of angular speed at which the agent can rotate.
var angular_speed_max := 0.0
# The maximum amount of angular acceleration that any behavior can apply to an agent.
# The maximum amount of angular acceleration that any behavior can apply to an
# agent.
var angular_acceleration_max := 0.0
# The current speed in a given direction the agent is traveling at.
# Current velocity of the agent.
var linear_velocity := Vector3.ZERO
# The current angular speed the agent is traveling at.
# Current angular velocity of the agent.
var angular_velocity := 0.0
# The radius of the sphere that approximates the agent's size in space.
var bounding_radius := 0.0
# Used internally by group behaviors and proximities to mark an agent as already considered.
# Used internally by group behaviors and proximities to mark the agent as already
# considered.
var tagged := false

View File

@ -1,24 +1,25 @@
class_name GSTSteeringBehavior
# The base class for all steering behaviors to extend. A steering behavior calculates the linear
# and/or angular acceleration to be applied to its owning agent
#
# The entry point for all behaviors is the `calculate_steering` function. Everything else is
# self-contained within the behavior.
# 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.
# Whether this behavior is enabled. All disabled behaviors return zero amounts of acceleration.
# Defaults to true
# If `false`, all calculations return zero amounts of acceleration.
var enabled := true
# The agent on which all steering calculations are to be made.
# The AI agent on which the steering behavior bases its calculations.
var agent: GSTSteeringAgent
# Initializes the behavior
func _init(agent: GSTSteeringAgent) -> void:
self.agent = agent
# Returns the `acceleration` parameter modified with the behavior's desired amount of acceleration
# Returns the `acceleration` modified with the behavior's desired amount of
# acceleration.
func calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration:
if enabled:
return _calculate_steering(acceleration)

View File

@ -1,14 +1,15 @@
class_name GSTTargetAcceleration
# A desired linear and angular amount of acceleration requested by the steering system.
# A desired linear and angular amount of acceleration requested by the steering
# system.
# The linear amount of acceleration
# Linear acceleration
var linear := Vector3.ZERO
# The angular amount of acceleration
# Angular acceleration
var angular := 0.0
# Sets the linear and angular components to 0
# Sets the linear and angular components to 0.
func set_zero() -> void:
linear.x = 0.0
linear.y = 0.0
@ -22,11 +23,11 @@ func add_scaled_accel(accel: GSTTargetAcceleration, scalar: float) -> void:
angular += accel.angular * scalar
# Returns the squared magnitude of the linear and angular components
# Returns the squared magnitude of the linear and angular components.
func get_magnitude_squared() -> float:
return linear.length_squared() + angular * angular
# Returns the magnitude of the linear and angular components
# Returns the magnitude of the linear and angular components.
func get_magnitude() -> float:
return sqrt(get_magnitude_squared())

View File

@ -1,8 +1,8 @@
class_name GSTUtils
# Useful math and vector manipulation functions to complement Godot's own.
# Math and vector utility functions.
# Returns the provided `vector` with its length capped to `limit`.
# Returns the `vector` with its length capped to `limit`.
static func clampedv3(vector: Vector3, limit: float) -> Vector3:
var length_squared := vector.length_squared()
var limit_squared := limit * limit
@ -11,7 +11,9 @@ static func clampedv3(vector: Vector3, limit: float) -> Vector3:
return vector
# Returns the provided vector as an angle in radians. This assumes orientation for 2D
# agents or 3D agents that are upright and rotate around the Y axis.
# Returns an angle in radians between the positive X axis and the `vector`.
#
# This assumes orientation for 2D agents or 3D agents that are upright and
# rotate around the Y axis.
static func vector_to_angle(vector: Vector3) -> float:
return atan2(vector.x, -vector.y)

View File

@ -1,12 +1,17 @@
extends GSTProximity
class_name GSTInfiniteProximity
# Determines any agent that is in the specified list as being neighbors with the owner agent.
# Determines any agent that is in the specified list as being neighbors with the
# owner agent.
func _init(agent: GSTSteeringAgent, agents: Array).(agent, agents) -> void:
pass
# 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 it if `callback` returns true.
func find_neighbors(callback: FuncRef) -> int:
var neighbor_count := 0
var agent_count := agents.size()
@ -16,5 +21,5 @@ func find_neighbors(callback: FuncRef) -> int:
if current_agent != agent:
if callback.call_func(current_agent):
neighbor_count += 1
return neighbor_count

View File

@ -1,7 +1,6 @@
extends Reference
class_name GSTProximity
# Defines a way to determine any agent that is in the specified list as being neighbors with the
# owner agent.
# Base container type that stores data to find the neighbors of an agent.
var agent: GSTSteeringAgent