mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2024-11-10 00:52:10 +01:00
166 lines
5.0 KiB
GDScript3
166 lines
5.0 KiB
GDScript3
|
# 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
|