2020-02-06 22:29:48 +01:00
|
|
|
# A specialized steering agent that updates itself every frame so the user does
|
|
|
|
# not have to using a KinematicBody
|
|
|
|
extends GSTSpecializedAgent
|
|
|
|
class_name GSTKinematicBodyAgent
|
|
|
|
|
2020-02-07 15:15:03 +01:00
|
|
|
# SLIDE uses `move_and_slide`
|
|
|
|
# COLLIDE uses `move_and_collide`
|
|
|
|
# POSITION changes the global_position directly
|
2020-02-07 11:29:45 +01:00
|
|
|
enum MovementType { SLIDE, COLLIDE, POSITION }
|
2020-02-06 22:29:48 +01:00
|
|
|
|
|
|
|
|
|
|
|
# The KinematicBody to keep track of
|
|
|
|
var body: KinematicBody setget _set_body
|
|
|
|
|
|
|
|
# The type of movement the body executes
|
2020-02-07 11:29:45 +01:00
|
|
|
var movement_type: int
|
2020-02-06 22:29:48 +01:00
|
|
|
|
|
|
|
var _last_position: Vector3
|
|
|
|
|
|
|
|
|
2020-02-07 11:29:45 +01:00
|
|
|
func _init(body: KinematicBody, movement_type: int = MovementType.SLIDE) -> void:
|
2020-02-07 15:15:03 +01:00
|
|
|
if not body.is_inside_tree():
|
|
|
|
yield(body, "ready")
|
2020-02-07 11:29:45 +01:00
|
|
|
|
2020-02-06 22:29:48 +01:00
|
|
|
self.body = body
|
2020-02-07 11:29:45 +01:00
|
|
|
self.movement_type = movement_type
|
|
|
|
|
|
|
|
body.get_tree().connect("physics_frame", self, "_on_SceneTree_physics_frame")
|
2020-02-06 22:29:48 +01:00
|
|
|
|
|
|
|
|
|
|
|
# Moves the agent's `body` by target `acceleration`.
|
|
|
|
# tags: virtual
|
2020-02-07 15:15:03 +01:00
|
|
|
func _apply_steering(acceleration: GSTTargetAcceleration, delta: float) -> void:
|
2020-02-06 22:29:48 +01:00
|
|
|
_applied_steering = true
|
2020-02-07 11:29:45 +01:00
|
|
|
match movement_type:
|
|
|
|
MovementType.COLLIDE:
|
2020-02-06 22:29:48 +01:00
|
|
|
_apply_collide_steering(acceleration.linear, delta)
|
2020-02-07 11:29:45 +01:00
|
|
|
MovementType.SLIDE:
|
2020-02-06 22:29:48 +01:00
|
|
|
_apply_sliding_steering(acceleration.linear)
|
|
|
|
_:
|
2020-02-07 11:29:45 +01:00
|
|
|
_apply_position_steering(acceleration.linear, delta)
|
2020-02-06 22:29:48 +01:00
|
|
|
|
|
|
|
_apply_orientation_steering(acceleration.angular, delta)
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2020-02-07 11:29:45 +01:00
|
|
|
func _apply_position_steering(accel: Vector3, delta: float) -> void:
|
2020-02-06 22:29:48 +01:00
|
|
|
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.y += velocity * delta
|
|
|
|
if calculate_velocities:
|
|
|
|
angular_velocity = velocity
|
|
|
|
|
|
|
|
|
|
|
|
func _set_body(value: KinematicBody) -> void:
|
|
|
|
body = value
|
|
|
|
|
|
|
|
_last_position = body.global_position
|
|
|
|
_last_orientation = body.rotation.y
|
|
|
|
|
|
|
|
position = _last_position
|
|
|
|
orientation = _last_orientation
|
|
|
|
|
|
|
|
|
2020-02-07 11:29:45 +01:00
|
|
|
func _on_SceneTree_physics_frame() -> void:
|
2020-02-06 22:29:48 +01:00
|
|
|
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:
|
|
|
|
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
|