diff --git a/project/demos/Arrive/Arriver.gd b/project/demos/Arrive/Arriver.gd index dedce81..e065805 100644 --- a/project/demos/Arrive/Arriver.gd +++ b/project/demos/Arrive/Arriver.gd @@ -1,7 +1,7 @@ extends KinematicBody2D -var agent := GSTSteeringAgent.new() +var agent := GSTNode2DAgent.new(self) var target := GSTAgentLocation.new() var arrive := GSTArrive.new(agent, target) var _accel := GSTTargetAcceleration.new() @@ -11,11 +11,8 @@ var _drag := 0.1 func _physics_process(delta: float) -> void: - _update_agent() arrive.calculate_steering(_accel) - _velocity += Vector2(_accel.linear.x, _accel.linear.y) - _velocity = _velocity.linear_interpolate(Vector2.ZERO, _drag).clamped(agent.linear_speed_max) - _velocity = move_and_slide(_velocity) + agent._apply_steering(_accel, delta) func setup( @@ -26,12 +23,7 @@ func setup( ) -> void: agent.linear_speed_max = linear_speed_max agent.linear_acceleration_max = linear_acceleration_max - agent.position = Vector3(global_position.x, global_position.y, 0) + agent.linear_drag_percentage = _drag arrive.deceleration_radius = deceleration_radius arrive.arrival_tolerance = arrival_tolerance target.position = agent.position - - -func _update_agent() -> void: - agent.position = Vector3(global_position.x, global_position.y, 0) - agent.linear_velocity = Vector3(_velocity.x, _velocity.y, 0) diff --git a/project/demos/AvoidCollisions/Avoider.gd b/project/demos/AvoidCollisions/Avoider.gd index 7027e13..3464351 100644 --- a/project/demos/AvoidCollisions/Avoider.gd +++ b/project/demos/AvoidCollisions/Avoider.gd @@ -13,7 +13,7 @@ var _drag := 0.1 var _color := Color(0.4, 1.0, 0.89, 0.3) onready var collision := $CollisionShape2D -onready var agent := GSTSteeringAgent.new() +onready var agent := GSTNode2DAgent.new(self) onready var proximity := GSTRadiusProximity.new(agent, [], 140) onready var avoid := GSTAvoidCollisions.new(agent, proximity) onready var target := GSTAgentLocation.new() @@ -27,12 +27,11 @@ func _draw() -> void: func _physics_process(delta: float) -> void: - _update_agent() + target.position.x = agent.position.x + _direction.x*_radius + target.position.y = agent.position.y + _direction.y*_radius + priority.calculate_steering(_accel) - _velocity += Vector2(_accel.linear.x, _accel.linear.y) - _velocity = _velocity.linear_interpolate(Vector2.ZERO, _drag) - _velocity = _velocity.clamped(agent.linear_speed_max) - _velocity = move_and_slide(_velocity) + agent._apply_steering(_accel, delta) func setup( @@ -46,15 +45,19 @@ func setup( ) -> void: rng.randomize() _direction = Vector2(rng.randf_range(-1, 1), rng.randf_range(-1, 1)).normalized() - _update_agent() + agent.linear_speed_max = linear_speed_max agent.linear_acceleration_max = linear_accel_max + proximity.radius = proximity_radius _boundary_bottom = boundary_bottom _boundary_right = boundary_right + _radius = collision.shape.radius agent.bounding_radius = _radius + agent.linear_drag_percentage = _drag + self.draw_proximity = draw_proximity priority.add(avoid) @@ -84,12 +87,3 @@ func set_random_nonoverlapping_position(others: Array, distance_from_boundary_mi done = false if done: break - - -func _update_agent() -> void: - agent.position.x = global_position.x - agent.position.y = global_position.y - agent.linear_velocity.x = _velocity.x - agent.linear_velocity.y = _velocity.y - target.position.x = agent.position.x + _direction.x*_radius - target.position.y = agent.position.y + _direction.y*_radius diff --git a/project/demos/Face/Turret.gd b/project/demos/Face/Turret.gd index 38fa4fa..6992a22 100644 --- a/project/demos/Face/Turret.gd +++ b/project/demos/Face/Turret.gd @@ -2,7 +2,7 @@ extends KinematicBody2D var face: GSTFace -var agent := GSTSteeringAgent.new() +var agent := GSTNode2DAgent.new(self) var _accel := GSTTargetAcceleration.new() var _angular_drag := 0.1 @@ -20,14 +20,7 @@ func _ready() -> void: func _physics_process(delta: float) -> void: face.calculate_steering(_accel) - agent.angular_velocity = clamp( - agent.angular_velocity + _accel.angular, - -agent.angular_speed_max, - agent.angular_speed_max - ) - agent.angular_velocity = lerp(agent.angular_velocity, 0, _angular_drag) - agent.orientation += agent.angular_velocity * delta - rotation = agent.orientation + agent._apply_steering(_accel, delta) func _draw() -> void: @@ -48,5 +41,4 @@ func setup( agent.angular_acceleration_max = angular_accel_max agent.angular_speed_max = angular_speed_max - agent.position = Vector3(global_position.x, global_position.y, 0) - + agent.angular_drag_percentage = _angular_drag diff --git a/project/demos/FollowPath/PathFollower.gd b/project/demos/FollowPath/PathFollower.gd index 9445050..cea97dd 100644 --- a/project/demos/FollowPath/PathFollower.gd +++ b/project/demos/FollowPath/PathFollower.gd @@ -6,7 +6,7 @@ var _accel := GSTTargetAcceleration.new() var _valid := false var _drag := 0.1 -onready var agent := GSTSteeringAgent.new() +onready var agent := GSTNode2DAgent.new(self) onready var path := GSTPath.new([ Vector3(global_position.x, global_position.y, 0), Vector3(global_position.x, global_position.y, 0) @@ -25,27 +25,18 @@ func setup( owner.drawer.connect("path_established", self, "_on_Drawer_path_established") follow.path_offset = path_offset follow.prediction_time = predict_time - agent.linear_acceleration_max = accel_max - agent.linear_speed_max = speed_max follow.deceleration_radius = decel_radius follow.arrival_tolerance = arrival_tolerance + + agent.linear_acceleration_max = accel_max + agent.linear_speed_max = speed_max + agent.linear_drag_percentage = _drag func _physics_process(delta: float) -> void: if _valid: - _update_agent() follow.calculate_steering(_accel) - _velocity += Vector2(_accel.linear.x, _accel.linear.y) - _velocity = _velocity.linear_interpolate(Vector2.ZERO, _drag) - _velocity = _velocity.clamped(agent.linear_speed_max) - _velocity = move_and_slide(_velocity) - - -func _update_agent() -> void: - agent.position.x = global_position.x - agent.position.y = global_position.y - agent.linear_velocity.x = _velocity.x - agent.linear_velocity.y = _velocity.y + agent._apply_steering(_accel, delta) func _on_Drawer_path_established(points: Array) -> void: diff --git a/project/demos/GroupBehaviors/Member.gd b/project/demos/GroupBehaviors/Member.gd index f3285a1..1658dd5 100644 --- a/project/demos/GroupBehaviors/Member.gd +++ b/project/demos/GroupBehaviors/Member.gd @@ -4,7 +4,7 @@ extends KinematicBody2D var separation: GSTSeparation var cohesion: GSTCohesion var proximity: GSTRadiusProximity -var agent := GSTSteeringAgent.new() +var agent := GSTNode2DAgent.new(self) var blend := GSTBlend.new(agent) var acceleration := GSTTargetAcceleration.new() var draw_proximity := false @@ -28,6 +28,7 @@ func setup( agent.linear_acceleration_max = linear_accel_max agent.linear_speed_max = linear_speed_max + agent.linear_drag_percentage = 0.1 proximity = GSTRadiusProximity.new(agent, [], proximity_radius) separation = GSTSeparation.new(agent, proximity) @@ -43,14 +44,9 @@ func _draw() -> void: func _physics_process(delta: float) -> void: - agent.position.x = global_position.x - agent.position.y = global_position.y if blend: blend.calculate_steering(acceleration) - _velocity += Vector2(acceleration.linear.x, acceleration.linear.y) - _velocity = _velocity.linear_interpolate(Vector2.ZERO, 0.1) - _velocity = _velocity.clamped(agent.linear_speed_max) - move_and_slide(_velocity) + agent._apply_steering(acceleration, delta) func set_neighbors(neighbor: Array) -> void: diff --git a/project/demos/GroupBehaviors/Member.tscn b/project/demos/GroupBehaviors/Member.tscn index 0baef77..c85ab3f 100644 --- a/project/demos/GroupBehaviors/Member.tscn +++ b/project/demos/GroupBehaviors/Member.tscn @@ -12,5 +12,6 @@ script = ExtResource( 1 ) [node name="CollisionShape2D" type="CollisionShape2D" parent="."] shape = SubResource( 1 ) script = ExtResource( 3 ) +inner_color = Color( 0, 0, 0, 1 ) outer_color = Color( 0.301961, 0.65098, 1, 1 ) stroke = 4.0 diff --git a/project/demos/PursueSeek/Pursuer.gd b/project/demos/PursueSeek/Pursuer.gd index 86cf241..37e245b 100644 --- a/project/demos/PursueSeek/Pursuer.gd +++ b/project/demos/PursueSeek/Pursuer.gd @@ -4,71 +4,68 @@ extends KinematicBody2D export var use_seek: bool = false -var _orient_behavior: GSTSteeringBehavior -var _behavior: GSTSteeringBehavior +var _blend: GSTBlend -var _linear_velocity := Vector2() var _linear_drag_coefficient := 0.025 -var _angular_velocity := 0.0 var _angular_drag := 0.1 var _direction_face := GSTAgentLocation.new() -onready var agent := GSTSteeringAgent.new() +onready var agent := GSTNode2DAgent.new(self) onready var accel := GSTTargetAcceleration.new() onready var player_agent: GSTSteeringAgent = owner.find_node("Player", true, false).agent func _ready() -> void: + agent.calculate_velocities = false set_physics_process(false) func _physics_process(delta: float) -> void: - _update_agent() - - _behavior.calculate_steering(accel) - _direction_face.position = agent.position + accel.linear.normalized() - _orient_behavior.calculate_steering(accel) - _angular_velocity += accel.angular - - _angular_velocity = clamp( - lerp(_angular_velocity, 0, _angular_drag), + _blend.calculate_steering(accel) + + agent.angular_velocity = clamp( + agent.angular_velocity + accel.angular, -agent.angular_speed_max, agent.angular_speed_max ) + agent.angular_velocity = lerp(agent.angular_velocity, 0, _angular_drag) + + rotation += agent.angular_velocity * delta - rotation += _angular_velocity * delta + var linear_velocity := ( + GSTUtils.to_vector2(agent.linear_velocity) + + (GSTUtils.angle_to_vector2(rotation) * -agent.linear_acceleration_max) + ) + linear_velocity = linear_velocity.clamped(agent.linear_speed_max) + linear_velocity = linear_velocity.linear_interpolate( + Vector2.ZERO, + _linear_drag_coefficient + ) - _linear_velocity += GSTUtils.angle_to_vector2(rotation) * -agent.linear_acceleration_max - _linear_velocity = _linear_velocity.clamped(agent.linear_speed_max) - _linear_velocity = _linear_velocity.linear_interpolate(Vector2.ZERO, _linear_drag_coefficient) - _linear_velocity = move_and_slide(_linear_velocity) + linear_velocity = move_and_slide(linear_velocity) + agent.linear_velocity = GSTUtils.to_vector3(linear_velocity) func setup(predict_time: float, linear_speed_max: float, linear_accel_max: float) -> void: + var behavior: GSTSteeringBehavior if use_seek: - _behavior = GSTSeek.new(agent, player_agent) + behavior = GSTSeek.new(agent, player_agent) else: - _behavior = GSTPursue.new(agent, player_agent, predict_time) + behavior = GSTPursue.new(agent, player_agent, predict_time) - _orient_behavior = GSTFace.new(agent, _direction_face) - _orient_behavior.alignment_tolerance = deg2rad(5) - _orient_behavior.deceleration_radius = deg2rad(5) + var orient_behavior := GSTFace.new(agent, _direction_face) + orient_behavior.alignment_tolerance = deg2rad(5) + orient_behavior.deceleration_radius = deg2rad(5) + + _blend = GSTBlend.new(agent) + _blend.add(behavior, 1) + _blend.add(orient_behavior, 1) agent.angular_acceleration_max = deg2rad(40) agent.angular_speed_max = deg2rad(90) agent.linear_acceleration_max = linear_accel_max agent.linear_speed_max = linear_speed_max - _update_agent() set_physics_process(true) - - -func _update_agent() -> void: - agent.position.x = global_position.x - agent.position.y = global_position.y - agent.orientation = rotation - agent.linear_velocity.x = _linear_velocity.x - agent.linear_velocity.y = _linear_velocity.y - agent.angular_velocity = _angular_velocity diff --git a/project/demos/SeekFlee/Seeker.gd b/project/demos/SeekFlee/Seeker.gd index 5dd86d6..da01af9 100644 --- a/project/demos/SeekFlee/Seeker.gd +++ b/project/demos/SeekFlee/Seeker.gd @@ -1,5 +1,4 @@ extends KinematicBody2D -# AI agent that uses the Seek behavior to hone in on the player's location as directly as possible. var player_agent: GSTAgentLocation @@ -8,7 +7,7 @@ var start_speed: float var start_accel: float var use_seek := true -onready var agent := GSTSteeringAgent.new() +onready var agent := GSTNode2DAgent.new(self) onready var accel := GSTTargetAcceleration.new() onready var seek := GSTSeek.new(agent, player_agent) onready var flee := GSTFlee.new(agent, player_agent) @@ -23,18 +22,9 @@ func _physics_process(delta: float) -> void: if not player_agent: return - _update_agent() if use_seek: seek.calculate_steering(accel) else: flee.calculate_steering(accel) - velocity = (velocity + Vector2(accel.linear.x, accel.linear.y)).clamped(agent.linear_speed_max) - velocity = move_and_slide(velocity) - - -func _update_agent() -> void: - agent.position.x = global_position.x - agent.position.y = global_position.y - agent.linear_velocity.x = velocity.x - agent.linear_velocity.y = velocity.y + agent._apply_steering(accel, delta) diff --git a/project/project.godot b/project/project.godot index d615c5b..f555a0d 100644 --- a/project/project.godot +++ b/project/project.godot @@ -74,6 +74,16 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://src/Behaviors/GSTMatchOrientation.gd" }, { +"base": "GSTNodeAgent", +"class": "GSTNode2DAgent", +"language": "GDScript", +"path": "res://src/Agents/GSTNode2DAgent.gd" +}, { +"base": "GSTSteeringAgent", +"class": "GSTNodeAgent", +"language": "GDScript", +"path": "res://src/Agents/GSTNodeAgent.gd" +}, { "base": "Reference", "class": "GSTPath", "language": "GDScript", @@ -109,6 +119,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://src/Behaviors/GSTSeparation.gd" }, { +"base": "GSTNodeAgent", +"class": "GSTSpatialAgent", +"language": "GDScript", +"path": "res://src/Agents/GSTSpatialAgent.gd" +}, { "base": "GSTAgentLocation", "class": "GSTSteeringAgent", "language": "GDScript", @@ -143,6 +158,8 @@ _global_script_class_icons={ "GSTInfiniteProximity": "", "GSTLookWhereYouGo": "", "GSTMatchOrientation": "", +"GSTNode2DAgent": "", +"GSTNodeAgent": "", "GSTPath": "", "GSTPriority": "", "GSTProximity": "", @@ -150,6 +167,7 @@ _global_script_class_icons={ "GSTRadiusProximity": "", "GSTSeek": "", "GSTSeparation": "", +"GSTSpatialAgent": "", "GSTSteeringAgent": "", "GSTSteeringBehavior": "", "GSTTargetAcceleration": "", diff --git a/project/reference.json b/project/reference.json deleted file mode 100644 index 1e9c8ba..0000000 --- a/project/reference.json +++ /dev/null @@ -1,2238 +0,0 @@ -[ - { - "name": "GSTArrive", - "path": "res://src/Behaviors/GSTArrive.gd", - "extends_class": [ - "GSTSteeringBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTArrive", - "description": " Calculates acceleration to take an agent to its target's location. The\n calculation attempts to arrive with zero remaining velocity.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "target", - "data_type": "GSTAgentLocation", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var target: GSTAgentLocation", - "description": " Target agent to arrive to.\n" - }, - { - "name": "arrival_tolerance", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var arrival_tolerance: float", - "description": " Distance from the target for the agent to be considered successfully\n arrived.\n" - }, - { - "name": "deceleration_radius", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var deceleration_radius: float", - "description": " Distance from the target for the agent to begin slowing down.\n" - }, - { - "name": "time_to_reach", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var time_to_reach: float", - "description": " Represents the time it takes to change acceleration.\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, target: GSTAgentLocation) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "target", - "type": "GSTAgentLocation" - } - ] - }, - { - "name": "_arrive", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _arrive(acceleration: GSTTargetAcceleration, target_position: Vector3) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - }, - { - "name": "target_position", - "type": "Vector3" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTAvoidCollisions", - "path": "res://src/Behaviors/GSTAvoidCollisions.gd", - "extends_class": [ - "GSTGroupBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTAvoidCollisions", - "description": " Steers the agent to avoid obstacles in its path. Approximates obstacles as\n spheres.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "_first_neighbor", - "data_type": "GSTSteeringAgent", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _first_neighbor: GSTSteeringAgent", - "description": "" - }, - { - "name": "_shortest_time", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _shortest_time: float", - "description": "" - }, - { - "name": "_first_minimum_separation", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _first_minimum_separation: float", - "description": "" - }, - { - "name": "_first_distance", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _first_distance: float", - "description": "" - }, - { - "name": "_first_relative_position", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _first_relative_position: Vector3", - "description": "" - }, - { - "name": "_first_relative_velocity", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _first_relative_velocity: Vector3", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, proximity: GSTProximity) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "proximity", - "type": "GSTProximity" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - }, - { - "name": "_report_neighbor", - "return_type": "bool", - "rpc_mode": 0, - "signature": "func _report_neighbor(neighbor: GSTSteeringAgent) -> bool", - "description": " Callback for the proximity to call when finding neighbors. Keeps track of every `neighbor`\n that was found but only keeps the one the owning agent will most likely collide with.\n tags: virtual\n", - "arguments": [ - { - "name": "neighbor", - "type": "GSTSteeringAgent" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTBlend", - "path": "res://src/Behaviors/GSTBlend.gd", - "extends_class": [ - "GSTSteeringBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTBlend", - "description": " Blends multiple steering behaviors into one, and returns a weighted\n acceleration from their calculations.\n\n Stores the behaviors internally as dictionaries of the form\n {\n \tbehavior : GSTSteeringBehavior,\n \tweight : float\n }\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "_behaviors", - "data_type": "Array", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _behaviors: Array", - "description": "" - }, - { - "name": "_accel", - "data_type": "GSTTargetAcceleration", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _accel: GSTTargetAcceleration", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - } - ] - }, - { - "name": "add", - "return_type": "null", - "rpc_mode": 0, - "signature": "func add(behavior: GSTSteeringBehavior, weight: float) -> null", - "description": " Appends a behavior to the internal array along with its `weight`.\n", - "arguments": [ - { - "name": "behavior", - "type": "GSTSteeringBehavior" - }, - { - "name": "weight", - "type": "float" - } - ] - }, - { - "name": "get_behavior_at", - "return_type": "Dictionary", - "rpc_mode": 0, - "signature": "func get_behavior_at(index: int) -> Dictionary", - "description": " Returns the behavior at the specified `index`, or an empty `Dictionary` if\n none was found.\n", - "arguments": [ - { - "name": "index", - "type": "int" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(blended_accel: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "blended_accel", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTCohesion", - "path": "res://src/Behaviors/GSTCohesion.gd", - "extends_class": [ - "GSTGroupBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTCohesion", - "description": " Calculates an acceleration that attempts to move the agent towards the center\n of mass of the agents in the area defined by the `GSTProximity`.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "_center_of_mass", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _center_of_mass: Vector3", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, proximity: GSTProximity) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "proximity", - "type": "GSTProximity" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - }, - { - "name": "_report_neighbor", - "return_type": "bool", - "rpc_mode": 0, - "signature": "func _report_neighbor(neighbor: GSTSteeringAgent) -> bool", - "description": " Callback for the proximity to call when finding neighbors. Adds `neighbor`'s position\n to the center of mass of the group.\n tags: virtual\n", - "arguments": [ - { - "name": "neighbor", - "type": "GSTSteeringAgent" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTEvade", - "path": "res://src/Behaviors/GSTEvade.gd", - "extends_class": [ - "GSTPursue" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTEvade", - "description": " Calculates acceleration to take an agent away from where a target agent is\n moving.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "var", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, target: GSTSteeringAgent, predict_time_max: float = 1)", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "target", - "type": "GSTSteeringAgent" - }, - { - "name": "predict_time_max", - "type": "float", - "default_value": 1 - } - ] - }, - { - "name": "_get_modified_acceleration", - "return_type": "float", - "rpc_mode": 0, - "signature": "func _get_modified_acceleration() -> float", - "description": "", - "arguments": [ - - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTFace", - "path": "res://src/Behaviors/GSTFace.gd", - "extends_class": [ - "GSTMatchOrientation" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTFace", - "description": " Calculates angular acceleration to rotate a target to face its target's\n position. The behavior attemps to arrive with zero remaining angular velocity.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, target: GSTAgentLocation) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "target", - "type": "GSTAgentLocation" - } - ] - }, - { - "name": "_face", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _face(acceleration: GSTTargetAcceleration, target_position: Vector3) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - }, - { - "name": "target_position", - "type": "Vector3" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTFlee", - "path": "res://src/Behaviors/GSTFlee.gd", - "extends_class": [ - "GSTSeek" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTFlee", - "description": " Calculates acceleration to take an agent directly away from a target agent.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, target: GSTAgentLocation) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "target", - "type": "GSTAgentLocation" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTFollowPath", - "path": "res://src/Behaviors/GSTFollowPath.gd", - "extends_class": [ - "GSTArrive" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTFollowPath", - "description": " Produces a linear acceleration that moves the agent along the specified path.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "path", - "data_type": "GSTPath", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var path: GSTPath", - "description": " The path to follow and travel along.\n" - }, - { - "name": "path_offset", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var path_offset: float", - "description": " The distance along the path to generate the next target position.\n" - }, - { - "name": "is_arrive_enabled", - "data_type": "bool", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var is_arrive_enabled: bool", - "description": " Whether to use `GSTArrive` behavior on an open path.\n" - }, - { - "name": "prediction_time", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var prediction_time: float", - "description": " The amount of time in the future to predict the owning agent's position along\n the path. Setting it to 0.0 will force non-predictive path following.\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, path: GSTPath, path_offset: float = 0, prediction_time: float = 0) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "path", - "type": "GSTPath" - }, - { - "name": "path_offset", - "type": "float", - "default_value": 0 - }, - { - "name": "prediction_time", - "type": "float", - "default_value": 0 - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTLookWhereYouGo", - "path": "res://src/Behaviors/GSTLookWhereYouGo.gd", - "extends_class": [ - "GSTMatchOrientation" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTLookWhereYouGo", - "description": " Calculates an angular acceleration to match an agent's orientation to its\n direction of travel.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(accel: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "accel", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTMatchOrientation", - "path": "res://src/Behaviors/GSTMatchOrientation.gd", - "extends_class": [ - "GSTSteeringBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTMatchOrientation", - "description": " Calculates an angular acceleration to match an agent's orientation to that of\n its target. Attempts to make the agent arrive with zero remaining angular\n velocity.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "target", - "data_type": "GSTAgentLocation", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var target: GSTAgentLocation", - "description": " The target orientation for the behavior to try and match rotations to.\n" - }, - { - "name": "alignment_tolerance", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var alignment_tolerance: float", - "description": " The amount of distance in radians for the behavior to consider itself close\n enough to be matching the target agent's rotation.\n" - }, - { - "name": "deceleration_radius", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var deceleration_radius: float", - "description": " The amount of distance in radians from the goal to start slowing down.\n" - }, - { - "name": "time_to_reach", - "data_type": "float", - "default_value": 0.1, - "setter": "", - "getter": "", - "export": false, - "signature": "var time_to_reach: float = 0.1", - "description": " The amount of time to reach the target velocity\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, target: GSTAgentLocation) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "target", - "type": "GSTAgentLocation" - } - ] - }, - { - "name": "_match_orientation", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _match_orientation(acceleration: GSTTargetAcceleration, desired_orientation: float) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - }, - { - "name": "desired_orientation", - "type": "float" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTPriority", - "path": "res://src/Behaviors/GSTPriority.gd", - "extends_class": [ - "GSTSteeringBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTPriority", - "description": " Container for multiple behaviors that returns the result of the first child\n behavior with non-zero acceleration.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "_behaviors", - "data_type": "Array", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _behaviors: Array", - "description": "" - }, - { - "name": "last_selected_index", - "data_type": "int", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var last_selected_index: int", - "description": " The index of the last behavior the container prioritized.\n" - }, - { - "name": "zero_threshold", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var zero_threshold: float", - "description": " If a behavior's acceleration is lower than this threshold, the container\n considers it has an acceleration of zero.\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, zero_threshold: float = 0.001) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "zero_threshold", - "type": "float", - "default_value": 0.001 - } - ] - }, - { - "name": "add", - "return_type": "null", - "rpc_mode": 0, - "signature": "func add(behavior: GSTSteeringBehavior) -> null", - "description": " Appends a steering behavior as a child of this container.\n", - "arguments": [ - { - "name": "behavior", - "type": "GSTSteeringBehavior" - } - ] - }, - { - "name": "get_behavior_at", - "return_type": "GSTSteeringBehavior", - "rpc_mode": 0, - "signature": "func get_behavior_at(index: int) -> GSTSteeringBehavior", - "description": " Returns the behavior at the position in the pool referred to by `index`, or\n `null` if no behavior was found.\n", - "arguments": [ - { - "name": "index", - "type": "int" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(accel: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "accel", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTPursue", - "path": "res://src/Behaviors/GSTPursue.gd", - "extends_class": [ - "GSTSteeringBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTPursue", - "description": " Calculates an acceleration to make an agent intercept another based on the\n target agent's movement.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "target", - "data_type": "GSTSteeringAgent", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var target: GSTSteeringAgent", - "description": " The target agent that the behavior is trying to intercept.\n" - }, - { - "name": "predict_time_max", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var predict_time_max: float", - "description": " The maximum amount of time in the future the behavior predicts the target's\n location.\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, target: GSTSteeringAgent, predict_time_max: float = 1) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "target", - "type": "GSTSteeringAgent" - }, - { - "name": "predict_time_max", - "type": "float", - "default_value": 1 - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - }, - { - "name": "_get_modified_acceleration", - "return_type": "float", - "rpc_mode": 0, - "signature": "func _get_modified_acceleration() -> float", - "description": "", - "arguments": [ - - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTSeek", - "path": "res://src/Behaviors/GSTSeek.gd", - "extends_class": [ - "GSTSteeringBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTSeek", - "description": " Calculates an acceleration to take an agent to a target agent's position\n directly.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "target", - "data_type": "GSTAgentLocation", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var target: GSTAgentLocation", - "description": " The target that the behavior aims to move the agent to.\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, target: GSTAgentLocation) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "target", - "type": "GSTAgentLocation" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTSeparation", - "path": "res://src/Behaviors/GSTSeparation.gd", - "extends_class": [ - "GSTGroupBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTSeparation", - "description": " Calculates an acceleration that repels the agent from its neighbors in the\n given `GSTProximity`.\n\n The acceleration is an average based on all neighbors, multiplied by a\n strength decreasing by the inverse square law in relation to distance, and it\n accumulates.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "decay_coefficient", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var decay_coefficient: float", - "description": " The coefficient to calculate how fast the separation strength decays with distance.\n" - }, - { - "name": "_acceleration", - "data_type": "GSTTargetAcceleration", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _acceleration: GSTTargetAcceleration", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, proximity: GSTProximity) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "proximity", - "type": "GSTProximity" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - }, - { - "name": "_report_neighbor", - "return_type": "bool", - "rpc_mode": 0, - "signature": "func _report_neighbor(neighbor: GSTSteeringAgent) -> bool", - "description": " Callback for the proximity to call when finding neighbors. Determines the amount of\n acceleration that `neighbor` imposes based on its distance from the owner agent.\n tags: virtual\n", - "arguments": [ - { - "name": "neighbor", - "type": "GSTSteeringAgent" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTAgentLocation", - "path": "res://src/GSTAgentLocation.gd", - "extends_class": [ - - ], - "extends_file": "", - "icon": "", - "signature": "class GSTAgentLocation", - "description": " Represents an agent with only a location and an orientation.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "position", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var position: Vector3", - "description": " The agent's position in space.\n" - }, - { - "name": "orientation", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var orientation: float", - "description": " The agent's orientation on its Y axis rotation.\n" - } - ], - "signals": [ - - ], - "methods": [ - - ], - "static_functions": [ - - ] - }, - { - "name": "GSTGroupBehavior", - "path": "res://src/GSTGroupBehavior.gd", - "extends_class": [ - "GSTSteeringBehavior" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTGroupBehavior", - "description": " Base type for group-based steering behaviors.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "proximity", - "data_type": "GSTProximity", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var proximity: GSTProximity", - "description": " Container to find neighbors of the agent and calculate group behavior.\n" - }, - { - "name": "_callback", - "data_type": "FuncRef", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _callback: FuncRef", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, proximity: GSTProximity) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "proximity", - "type": "GSTProximity" - } - ] - }, - { - "name": "_report_neighbor", - "return_type": "bool", - "rpc_mode": 0, - "signature": "func _report_neighbor(neighbor: GSTSteeringAgent) -> bool", - "description": " Internal callback for the behavior to define whether or not a member is\n relevant\n tags: virtual\n", - "arguments": [ - { - "name": "neighbor", - "type": "GSTSteeringAgent" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTPath", - "path": "res://src/GSTPath.gd", - "extends_class": [ - "Reference" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTPath", - "description": " Represents a path made up of Vector3 waypoints, split into segments path\n follow behaviors can use.\n", - "sub_classes": [ - { - "name": "GSTSegment", - "path": "res://src/GSTPath.gd", - "extends_class": [ - - ], - "extends_file": "", - "icon": "", - "signature": "class GSTSegment", - "description": "", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "begin", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var begin: Vector3", - "description": "" - }, - { - "name": "end", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var end: Vector3", - "description": "" - }, - { - "name": "length", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var length: float", - "description": "" - }, - { - "name": "cumulative_length", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var cumulative_length: float", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(begin: Vector3, end: Vector3) -> null", - "description": "", - "arguments": [ - { - "name": "begin", - "type": "Vector3" - }, - { - "name": "end", - "type": "Vector3" - } - ] - } - ], - "static_functions": [ - - ] - } - ], - "constants": [ - - ], - "members": [ - { - "name": "is_open", - "data_type": "bool", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var is_open: bool", - "description": " If `false`, the path loops.\n" - }, - { - "name": "length", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var length: float", - "description": " Total length of the path.\n" - }, - { - "name": "_segments", - "data_type": "Array", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _segments: Array", - "description": "" - }, - { - "name": "_nearest_point_on_segment", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _nearest_point_on_segment: Vector3", - "description": "" - }, - { - "name": "_nearest_point_on_path", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _nearest_point_on_path: Vector3", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(waypoints: Array, is_open: bool = false) -> null", - "description": "", - "arguments": [ - { - "name": "waypoints", - "type": "Array" - }, - { - "name": "is_open", - "type": "bool", - "default_value": false - } - ] - }, - { - "name": "create_path", - "return_type": "null", - "rpc_mode": 0, - "signature": "func create_path(waypoints: Array) -> null", - "description": " Creates a path from a list of waypoints.\n", - "arguments": [ - { - "name": "waypoints", - "type": "Array" - } - ] - }, - { - "name": "calculate_distance", - "return_type": "float", - "rpc_mode": 0, - "signature": "func calculate_distance(agent_current_position: Vector3) -> float", - "description": " Returns the distance from `agent_current_position` to the next waypoint.\n", - "arguments": [ - { - "name": "agent_current_position", - "type": "Vector3" - } - ] - }, - { - "name": "calculate_target_position", - "return_type": "Vector3", - "rpc_mode": 0, - "signature": "func calculate_target_position(target_distance: float) -> Vector3", - "description": " Calculates a target position from the path's starting point based on the `target_distance`.\n", - "arguments": [ - { - "name": "target_distance", - "type": "float" - } - ] - }, - { - "name": "get_start_point", - "return_type": "Vector3", - "rpc_mode": 0, - "signature": "func get_start_point() -> Vector3", - "description": " Returns the position of the first point on the path.\n", - "arguments": [ - - ] - }, - { - "name": "get_end_point", - "return_type": "Vector3", - "rpc_mode": 0, - "signature": "func get_end_point() -> Vector3", - "description": " Returns the position of the last point on the path.\n", - "arguments": [ - - ] - }, - { - "name": "_calculate_point_segment_distance_squared", - "return_type": "float", - "rpc_mode": 0, - "signature": "func _calculate_point_segment_distance_squared(start: Vector3, end: Vector3, position: Vector3) -> float", - "description": "", - "arguments": [ - { - "name": "start", - "type": "Vector3" - }, - { - "name": "end", - "type": "Vector3" - }, - { - "name": "position", - "type": "Vector3" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTSteeringAgent", - "path": "res://src/GSTSteeringAgent.gd", - "extends_class": [ - "GSTAgentLocation" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTSteeringAgent", - "description": " Adds velocity, speed, and size data to `GSTAgentLocation`.\n\n It is the character's responsibility to keep this information up to date for\n the steering toolkit to work correctly.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "zero_linear_speed_threshold", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var zero_linear_speed_threshold: float", - "description": " The amount of velocity to be considered effectively not moving.\n" - }, - { - "name": "linear_speed_max", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var linear_speed_max: float", - "description": " The maximum speed at which the agent can move.\n" - }, - { - "name": "linear_acceleration_max", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var linear_acceleration_max: float", - "description": " The maximum amount of acceleration that any behavior can apply to the agent.\n" - }, - { - "name": "angular_speed_max", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var angular_speed_max: float", - "description": " The maximum amount of angular speed at which the agent can rotate.\n" - }, - { - "name": "angular_acceleration_max", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var angular_acceleration_max: float", - "description": " The maximum amount of angular acceleration that any behavior can apply to an\n agent.\n" - }, - { - "name": "linear_velocity", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var linear_velocity: Vector3", - "description": " Current velocity of the agent.\n" - }, - { - "name": "angular_velocity", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var angular_velocity: float", - "description": " Current angular velocity of the agent.\n" - }, - { - "name": "bounding_radius", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var bounding_radius: float", - "description": " The radius of the sphere that approximates the agent's size in space.\n" - }, - { - "name": "is_tagged", - "data_type": "bool", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var is_tagged: bool", - "description": " Used internally by group behaviors and proximities to mark the agent as already\n considered.\n" - } - ], - "signals": [ - - ], - "methods": [ - - ], - "static_functions": [ - - ] - }, - { - "name": "GSTSteeringBehavior", - "path": "res://src/GSTSteeringBehavior.gd", - "extends_class": [ - - ], - "extends_file": "", - "icon": "", - "signature": "class GSTSteeringBehavior", - "description": " Base class for all steering behaviors.\n\n Steering behaviors calculate the linear and the angular acceleration to be\n to the agent that owns them.\n\n The `calculate_steering` function is the entry point for all behaviors.\n Individual steering behaviors encapsulate the steering logic.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "is_enabled", - "data_type": "bool", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var is_enabled: bool", - "description": " If `false`, all calculations return zero amounts of acceleration.\n" - }, - { - "name": "agent", - "data_type": "GSTSteeringAgent", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var agent: GSTSteeringAgent", - "description": " The AI agent on which the steering behavior bases its calculations.\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - } - ] - }, - { - "name": "calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": " Returns the `acceleration` modified with the behavior's desired amount of\n acceleration.\n", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - }, - { - "name": "_calculate_steering", - "return_type": "GSTTargetAcceleration", - "rpc_mode": 0, - "signature": "func _calculate_steering(acceleration: GSTTargetAcceleration) -> GSTTargetAcceleration", - "description": "", - "arguments": [ - { - "name": "acceleration", - "type": "GSTTargetAcceleration" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTTargetAcceleration", - "path": "res://src/GSTTargetAcceleration.gd", - "extends_class": [ - - ], - "extends_file": "", - "icon": "", - "signature": "class GSTTargetAcceleration", - "description": " A desired linear and angular amount of acceleration requested by the steering\n system.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "linear", - "data_type": "Vector3", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var linear: Vector3", - "description": " Linear acceleration\n" - }, - { - "name": "angular", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var angular: float", - "description": " Angular acceleration\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "set_zero", - "return_type": "null", - "rpc_mode": 0, - "signature": "func set_zero() -> null", - "description": " Sets the linear and angular components to 0.\n", - "arguments": [ - - ] - }, - { - "name": "add_scaled_accel", - "return_type": "null", - "rpc_mode": 0, - "signature": "func add_scaled_accel(accel: GSTTargetAcceleration, scalar: float) -> null", - "description": " Adds `accel`'s components, multiplied by `scalar`, to this one.\n", - "arguments": [ - { - "name": "accel", - "type": "GSTTargetAcceleration" - }, - { - "name": "scalar", - "type": "float" - } - ] - }, - { - "name": "get_magnitude_squared", - "return_type": "float", - "rpc_mode": 0, - "signature": "func get_magnitude_squared() -> float", - "description": " Returns the squared magnitude of the linear and angular components.\n", - "arguments": [ - - ] - }, - { - "name": "get_magnitude", - "return_type": "float", - "rpc_mode": 0, - "signature": "func get_magnitude() -> float", - "description": " Returns the magnitude of the linear and angular components.\n", - "arguments": [ - - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTUtils", - "path": "res://src/GSTUtils.gd", - "extends_class": [ - - ], - "extends_file": "", - "icon": "", - "signature": "class GSTUtils", - "description": " Math and vector utility functions.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - - ], - "signals": [ - - ], - "methods": [ - - ], - "static_functions": [ - { - "name": "clampedv3", - "return_type": "Vector3", - "rpc_mode": 0, - "signature": "func clampedv3(vector: Vector3, limit: float) -> Vector3", - "description": " Returns the `vector` with its length capped to `limit`.\n", - "arguments": [ - { - "name": "vector", - "type": "Vector3" - }, - { - "name": "limit", - "type": "float" - } - ] - }, - { - "name": "vector3_to_angle", - "return_type": "float", - "rpc_mode": 0, - "signature": "func vector3_to_angle(vector: Vector3) -> float", - "description": " Returns an angle in radians between the positive X axis and the `vector`.\n\n This assumes orientation for 2D agents or 3D agents that are upright and\n rotate around the Y axis.\n", - "arguments": [ - { - "name": "vector", - "type": "Vector3" - } - ] - }, - { - "name": "angle_to_vector2", - "return_type": "Vector2", - "rpc_mode": 0, - "signature": "func angle_to_vector2(angle: float) -> Vector2", - "description": " Returns a directional vector from the given orientation angle.\n \n This assumes orientation for 2D agents or 3D agents that are upright and\n rotate around the Y axis.\n", - "arguments": [ - { - "name": "angle", - "type": "float" - } - ] - } - ] - }, - { - "name": "GSTInfiniteProximity", - "path": "res://src/Proximities/GSTInfiniteProximity.gd", - "extends_class": [ - "GSTProximity" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTInfiniteProximity", - "description": " Determines any agent that is in the specified list as being neighbors with the\n owner agent, regardless of distance.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, agents: Array) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "agents", - "type": "Array" - } - ] - }, - { - "name": "_find_neighbors", - "return_type": "int", - "rpc_mode": 0, - "signature": "func _find_neighbors(callback: FuncRef) -> int", - "description": " Returns a number of neighbors based on a `callback` function.\n\n `_find_neighbors` calls `callback` for each agent in the `agents` array and\n adds one to the count if its `callback` returns true.\n tags: virtual\n", - "arguments": [ - { - "name": "callback", - "type": "FuncRef" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTProximity", - "path": "res://src/Proximities/GSTProximity.gd", - "extends_class": [ - "Reference" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTProximity", - "description": " Base container type that stores data to find the neighbors of an agent.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "agent", - "data_type": "GSTSteeringAgent", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var agent: GSTSteeringAgent", - "description": " The owning agent whose neighbors are found in the group\n" - }, - { - "name": "agents", - "data_type": "Array", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var agents: Array", - "description": " The agents who are part of this group and could be potential neighbors\n" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, agents: Array) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "agents", - "type": "Array" - } - ] - }, - { - "name": "_find_neighbors", - "return_type": "int", - "rpc_mode": 0, - "signature": "func _find_neighbors(callback: FuncRef) -> int", - "description": " Returns a number of neighbors based on a `callback` function.\n\n `_find_neighbors` calls `callback` for each agent in the `agents` array and\n adds one to the count if its `callback` returns true.\n tags: virtual\n", - "arguments": [ - { - "name": "callback", - "type": "FuncRef" - } - ] - } - ], - "static_functions": [ - - ] - }, - { - "name": "GSTRadiusProximity", - "path": "res://src/Proximities/GSTRadiusProximity.gd", - "extends_class": [ - "GSTProximity" - ], - "extends_file": "", - "icon": "", - "signature": "class GSTRadiusProximity", - "description": " Determines any agent that is in the specified list as being neighbors with the owner agent if\n they lie within the specified radius.\n", - "sub_classes": [ - - ], - "constants": [ - - ], - "members": [ - { - "name": "radius", - "data_type": "float", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var radius: float", - "description": " The radius around the owning agent to find neighbors in\n" - }, - { - "name": "_last_frame", - "data_type": "int", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _last_frame: int", - "description": "" - }, - { - "name": "_scene_tree", - "data_type": "SceneTree", - "default_value": null, - "setter": "", - "getter": "", - "export": false, - "signature": "var _scene_tree: SceneTree", - "description": "" - } - ], - "signals": [ - - ], - "methods": [ - { - "name": "_init", - "return_type": "null", - "rpc_mode": 0, - "signature": "func _init(agent: GSTSteeringAgent, agents: Array, radius: float) -> null", - "description": "", - "arguments": [ - { - "name": "agent", - "type": "GSTSteeringAgent" - }, - { - "name": "agents", - "type": "Array" - }, - { - "name": "radius", - "type": "float" - } - ] - }, - { - "name": "_find_neighbors", - "return_type": "int", - "rpc_mode": 0, - "signature": "func _find_neighbors(callback: FuncRef) -> int", - "description": " Returns a number of neighbors based on a `callback` function.\n\n `_find_neighbors` calls `callback` for each agent in the `agents` array that lie within\n the radius around the owning agent and adds one to the count if its `callback` returns true.\n tags: virtual\n", - "arguments": [ - { - "name": "callback", - "type": "FuncRef" - } - ] - } - ], - "static_functions": [ - - ] - } -] \ No newline at end of file diff --git a/project/src/Agents/GSTNode2DAgent.gd b/project/src/Agents/GSTNode2DAgent.gd new file mode 100644 index 0000000..dd4d0b9 --- /dev/null +++ b/project/src/Agents/GSTNode2DAgent.gd @@ -0,0 +1,165 @@ +# A specialized steering agent that updates itself every frame so the user does +# not have to. +extends GSTNodeAgent +class_name GSTNode2DAgent + + +# The Node2D to keep track of +var body: Node2D setget _set_body + +var _last_position: Vector2 + + +func _init(body: Node2D) -> void: + self.body = body + if body.is_inside_tree(): + body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame") + else: + body.connect("ready", self, "_on_body_ready") + + +# Moves the agent's `body` by target `acceleration`. +# tags: virtual +func _apply_steering(acceleration: GSTTargetAcceleration, delta: float) -> void: + _applied_steering = true + match _body_type: + BodyType.RIGID: + _apply_rigid_steering(acceleration) + BodyType.KINEMATIC: + match kinematic_movement_type: + MovementType.COLLIDE: + _apply_collide_steering(acceleration.linear, delta) + MovementType.SLIDE: + _apply_sliding_steering(acceleration.linear) + MovementType.POSITION: + _apply_normal_steering(acceleration.linear, delta) + BodyType.NODE: + _apply_normal_steering(acceleration.linear, delta) + if not _body_type == BodyType.RIGID: + _apply_orientation_steering(acceleration.angular, delta) + + +func _apply_rigid_steering(accel: GSTTargetAcceleration) -> void: + body.apply_central_impulse(GSTUtils.to_vector2(accel.linear)) + body.apply_torque_impulse(accel.angular) + if calculate_velocities: + linear_velocity = GSTUtils.to_vector3(body.linear_velocity) + angular_velocity = body.angular_velocity + + +func _apply_sliding_steering(accel: Vector3) -> void: + var velocity := GSTUtils.to_vector2(linear_velocity + accel).clamped(linear_speed_max) + if apply_linear_drag: + velocity = velocity.linear_interpolate(Vector2.ZERO, linear_drag_percentage) + velocity = body.move_and_slide(velocity) + if calculate_velocities: + linear_velocity = GSTUtils.to_vector3(velocity) + + +func _apply_collide_steering(accel: Vector3, delta: float) -> void: + var velocity := GSTUtils.clampedv3(linear_velocity + accel, linear_speed_max) + if apply_linear_drag: + velocity = velocity.linear_interpolate( + Vector3.ZERO, + linear_drag_percentage + ) + body.move_and_collide(GSTUtils.to_vector2(velocity) * delta) + if calculate_velocities: + linear_velocity = velocity + + +func _apply_normal_steering(accel: Vector3, delta: float) -> void: + var velocity := GSTUtils.clampedv3(linear_velocity + accel, linear_speed_max) + if apply_linear_drag: + velocity = velocity.linear_interpolate( + Vector3.ZERO, + linear_drag_percentage + ) + body.global_position += GSTUtils.to_vector2(velocity) * delta + if calculate_velocities: + linear_velocity = velocity + + +func _apply_orientation_steering(angular_acceleration: float, delta: float) -> void: + var velocity = angular_velocity + angular_acceleration + if apply_angular_drag: + velocity = lerp(velocity, 0, angular_drag_percentage) + body.rotation += velocity * delta + if calculate_velocities: + angular_velocity = velocity + + +func _set_use_physics(value: bool) -> void: + if use_physics and not value: + body.get_tree().disconnect("idle_frame", self, "_on_SceneTree_frame") + body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame") + elif not use_physics and value: + body.get_tree().disconnect("physics_frame", self, "_on_SceneTree_frame") + body.get_tree().connect("idle_frame", self, "_on_SceneTree_frame") + use_physics = value + + +func _set_body(value: Node2D) -> void: + body = value + if body is RigidBody2D: + _body_type = BodyType.RIGID + elif body is KinematicBody2D: + _body_type = BodyType.KINEMATIC + else: + _body_type = BodyType.NODE + + if _body_type == BodyType.RIGID: + linear_velocity = GSTUtils.to_vector3(body.linear_velocity) + angular_velocity = body.angular_velocity + else: + _last_position = body.global_position + _last_orientation = body.rotation + + position = GSTUtils.to_vector3(_last_position) + orientation = _last_orientation + + +func _on_body_ready() -> void: + body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame") + _set_body(body) + + +func _on_SceneTree_frame() -> void: + var current_position: Vector2 = body.global_position + var current_orientation: float = body.rotation + + position = GSTUtils.to_vector3(current_position) + orientation = current_orientation + + if calculate_velocities: + if _applied_steering: + _applied_steering = false + else: + match _body_type: + BodyType.RIGID: + linear_velocity = GSTUtils.to_vector3(body.linear_velocity) + angular_velocity = body.angular_velocity + _: + linear_velocity = GSTUtils.clampedv3( + GSTUtils.to_vector3(_last_position - current_position), + linear_speed_max + ) + if apply_linear_drag: + linear_velocity = linear_velocity.linear_interpolate( + Vector3.ZERO, + linear_drag_percentage + ) + angular_velocity = clamp( + _last_orientation - current_orientation, + -angular_speed_max, + angular_speed_max + ) + if apply_angular_drag: + angular_velocity = lerp( + angular_velocity, + 0, + angular_drag_percentage + ) + + _last_position = current_position + _last_orientation = current_orientation diff --git a/project/src/Agents/GSTNodeAgent.gd b/project/src/Agents/GSTNodeAgent.gd new file mode 100644 index 0000000..f69e06b --- /dev/null +++ b/project/src/Agents/GSTNodeAgent.gd @@ -0,0 +1,79 @@ +# A base class for a specialized steering agent that updates itself every frame +# so the user does not have to. +extends GSTSteeringAgent +class_name GSTNodeAgent + + +enum MovementType { SLIDE, COLLIDE, POSITION } + +enum BodyType { NODE, KINEMATIC, RIGID } + + +# If `true`, will update before `_physics_process` is called. If `false`, will +# update before `_process` is called. +# +# `KinematicBody`, `KinematicBody2D`, `RigidBody`, and `RigidBody2D` should +# always use `_physics_process`. +var use_physics := true setget _set_use_physics + +# If `true`, will calculate linear and angular velocities based on the previous +# frame. When `false`, the user must keep those values updated. +var calculate_velocities := true + +# If `true` and velocities and `calculate_velocities` is true, will interpolate +# the current linear velocity towards 0 by the `linear_drag_percentage` value. +# Does not apply to `RigidBody` and `RigidBody2D` nodes. +var apply_linear_drag := true + +# If `true` and velocities and `calculate_velocities` is true, will interpolate +# the current angular velocity towards 0 by the `angular_drag_percentage` value. +# Does not apply to `RigidBody` and `RigidBody2D` nodes. +var apply_angular_drag := true + +# The percentage between the current linear velocity and 0 to interpolate by if +# `calculate_velocities` and `apply_linear_drag` are true. +# Does not apply to `RigidBody` and `RigidBody2D` nodes. +var linear_drag_percentage := 0.0 + +# The percentage between the current angular velocity and 0 to interpolate by if +# `calculate_velocities` and `apply_angular_drag` are true. +# Does not apply to `RigidBody` and `RigidBody2D` nodes. +var angular_drag_percentage := 0.0 + +# Determines how linear movement occurs if the body is a `KinematicBody` or +# `KinematicBody2D`. +# +# SLIDE uses `move_and_slide` +# COLLIDE uses `move_and_collide` +# POSITION changes global position directly +var kinematic_movement_type: int = MovementType.SLIDE + +var _last_orientation: float +var _body_type: int +var _applied_steering := false + + +# Moves the agent's body by target `acceleration`. +# tags: virtual +func _apply_steering(acceleration: GSTTargetAcceleration, delta: float) -> void: + pass + + +func _apply_sliding_steering(accel: Vector3) -> void: + pass + + +func _apply_collide_steering(accel: Vector3, delta: float) -> void: + pass + + +func _apply_normal_steering(accel: Vector3, delta: float) -> void: + pass + + +func _apply_orientation_steering(angular_acceleration: float, delta: float) -> void: + pass + + +func _set_use_physics(value: bool) -> void: + use_physics = value diff --git a/project/src/Agents/GSTSpatialAgent.gd b/project/src/Agents/GSTSpatialAgent.gd new file mode 100644 index 0000000..b145530 --- /dev/null +++ b/project/src/Agents/GSTSpatialAgent.gd @@ -0,0 +1,166 @@ +# A specialized steering agent that updates itself every frame so the user does +# not have to. +extends GSTNodeAgent +class_name GSTSpatialAgent + + +# The Spatial to keep track of +var body: Spatial setget _set_body + +var _last_position: Vector3 + + +func _init(body: Spatial) -> void: + self.body = body + if body.is_inside_tree(): + body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame") + else: + body.connect("ready", self, "_on_body_ready") + + +# Moves the agent's `body` by target `acceleration`. +# tags: virtual +func _apply_steering(acceleration: GSTTargetAcceleration, delta: float) -> void: + _applied_steering = true + match _body_type: + BodyType.RIGID: + _apply_rigid_steering(acceleration) + BodyType.KINEMATIC: + match kinematic_movement_type: + MovementType.COLLIDE: + _apply_collide_steering(acceleration.linear, delta) + MovementType.SLIDE: + _apply_sliding_steering(acceleration.linear) + MovementType.POSITION: + _apply_normal_steering(acceleration.linear, delta) + BodyType.NODE: + _apply_normal_steering(acceleration.linear, delta) + if not _body_type == BodyType.RIGID: + _apply_orientation_steering(acceleration.angular, delta) + + +func _apply_rigid_steering(accel: GSTTargetAcceleration) -> void: + body.apply_central_impulse(GSTUtils.to_Vector3(accel.linear)) + body.apply_torque_impulse(accel.angular) + if calculate_velocities: + linear_velocity = body.linear_velocity + angular_velocity = body.angular_velocity.y + + +func _apply_sliding_steering(accel: Vector3) -> void: + var velocity := GSTUtils.clampedv3(linear_velocity + accel, linear_speed_max) + if apply_linear_drag: + velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage) + velocity = body.move_and_slide(velocity) + if calculate_velocities: + linear_velocity = velocity + + +func _apply_collide_steering(accel: Vector3, delta: float) -> void: + var velocity := GSTUtils.clampedv3(linear_velocity + accel, linear_speed_max) + if apply_linear_drag: + velocity = velocity.linear_interpolate( + Vector3.ZERO, + linear_drag_percentage + ) + body.move_and_collide(velocity * delta) + if calculate_velocities: + linear_velocity = velocity + + +func _apply_normal_steering(accel: Vector3, delta: float) -> void: + var velocity := GSTUtils.clampedv3(linear_velocity + accel, linear_speed_max) + if apply_linear_drag: + velocity = velocity.linear_interpolate( + Vector3.ZERO, + linear_drag_percentage + ) + body.global_position += velocity * delta + if calculate_velocities: + linear_velocity = velocity + + +func _apply_orientation_steering(angular_acceleration: float, delta: float) -> void: + var velocity = angular_velocity + angular_acceleration + if apply_angular_drag: + velocity = lerp(velocity, 0, angular_drag_percentage) + body.rotation += velocity * delta + if calculate_velocities: + angular_velocity = velocity + + +func _set_use_physics(value: bool) -> void: + if use_physics and not value: + body.get_tree().disconnect("idle_frame", self, "_on_SceneTree_frame") + body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame") + elif not use_physics and value: + body.get_tree().disconnect("physics_frame", self, "_on_SceneTree_frame") + body.get_tree().connect("idle_frame", self, "_on_SceneTree_frame") + use_physics = value + + +func _set_body(value: Spatial) -> void: + body = value + if body is RigidBody: + _body_type = BodyType.RIGID + elif body is KinematicBody: + _body_type = BodyType.KINEMATIC + else: + _body_type = BodyType.NODE + + if _body_type == BodyType.RIGID: + linear_velocity = body.linear_velocity + angular_velocity = body.angular_velocity + else: + _last_position = body.global_position + _last_orientation = body.rotation.y + + position = _last_position + orientation = _last_orientation + + +func _on_body_ready() -> void: + body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame") + body.disconnect("ready", self, "_on_body_ready") + _set_body(body) + + +func _on_SceneTree_frame() -> void: + var current_position: Vector3 = body.global_position + var current_orientation: float = body.rotation.y + + position = current_position + orientation = current_orientation + + if calculate_velocities: + if _applied_steering: + _applied_steering = false + else: + match _body_type: + BodyType.RIGID: + linear_velocity = GSTUtils.to_vector3(body.linear_velocity) + angular_velocity = body.angular_velocity + _: + linear_velocity = GSTUtils.clampedv3( + _last_position - current_position, + linear_speed_max + ) + if apply_linear_drag: + linear_velocity = linear_velocity.linear_interpolate( + Vector3.ZERO, + linear_drag_percentage + ) + angular_velocity = clamp( + _last_orientation - current_orientation, + -angular_speed_max, + angular_speed_max + ) + if apply_angular_drag: + angular_velocity = lerp( + angular_velocity, + 0, + angular_drag_percentage + ) + + _last_position = current_position + _last_orientation = current_orientation diff --git a/project/src/GSTUtils.gd b/project/src/GSTUtils.gd index d3e1c89..bbe5e34 100644 --- a/project/src/GSTUtils.gd +++ b/project/src/GSTUtils.gd @@ -25,3 +25,13 @@ static func vector3_to_angle(vector: Vector3) -> float: # rotate around the Y axis. static func angle_to_vector2(angle: float) -> Vector2: return Vector2(sin(-angle), cos(angle)) + + +# Returns a vector2 with `vector`'s x and y components. +static func to_vector2(vector: Vector3) -> Vector2: + return Vector2(vector.x, vector.y) + + +# Returns a vector3 with `vector`'s x and y components and 0 in z. +static func to_vector3(vector: Vector2) -> Vector3: + return Vector3(vector.x, vector.y, 0)