2025-02-03 01:00:55 +00:00
|
|
|
extends RigidBody3D
|
2025-02-02 19:01:03 +00:00
|
|
|
|
|
|
|
# Local coords to axis
|
|
|
|
# Yaw = Y
|
|
|
|
# Roll = Z
|
|
|
|
# Pitch = X
|
|
|
|
|
|
|
|
@export_category("Parameters")
|
|
|
|
@export var flight_modes: Array = ["normal", "acro"]
|
2025-02-04 03:47:25 +00:00
|
|
|
@export var throttle_curve: Curve
|
2025-02-02 19:01:03 +00:00
|
|
|
@export var armed: bool = false
|
2025-02-03 01:00:55 +00:00
|
|
|
@export var can_flip: bool = false
|
2025-02-02 19:01:03 +00:00
|
|
|
@export var throttle_speed: float = 0.0
|
2025-02-04 03:47:25 +00:00
|
|
|
@export var rotation_speed: float = 0.06
|
2025-02-04 02:00:37 +00:00
|
|
|
@export var max_speed: float = 20.0
|
2025-02-03 04:55:33 +00:00
|
|
|
@export var max_rotation_speed: float = 15.0
|
2025-02-04 02:00:37 +00:00
|
|
|
@export var thrust_factor: float = 1.0
|
2025-02-02 19:01:03 +00:00
|
|
|
@export_category("Node References")
|
|
|
|
@export var camera: Camera3D
|
|
|
|
@export var anim_player: AnimationPlayer
|
2025-02-03 01:00:55 +00:00
|
|
|
@export var flip_over_detection_ray: RayCast3D
|
|
|
|
@export var flip_over_timer: Timer
|
|
|
|
@export var input_suggestion_label: Label
|
2025-02-03 04:55:33 +00:00
|
|
|
@export var reset_point: Marker3D
|
2025-02-02 19:01:03 +00:00
|
|
|
|
|
|
|
var animation_initalized: bool = false
|
|
|
|
var using_joy_controller: bool = true
|
|
|
|
|
|
|
|
|
|
|
|
func _ready():
|
2025-02-03 01:00:55 +00:00
|
|
|
flip_over_timer.timeout.connect(_on_flip_over_timeout)
|
2025-02-02 19:01:03 +00:00
|
|
|
|
|
|
|
|
2025-02-03 01:00:55 +00:00
|
|
|
func _process(_delta):
|
|
|
|
if Input.is_action_just_pressed("arm"):
|
|
|
|
handle_arming()
|
|
|
|
|
|
|
|
|
2025-02-02 19:01:03 +00:00
|
|
|
func handle_arming():
|
|
|
|
if !armed:
|
|
|
|
if !animation_initalized:
|
|
|
|
anim_player.play("spin_props")
|
|
|
|
animation_initalized = true
|
|
|
|
elif animation_initalized:
|
|
|
|
anim_player.play()
|
|
|
|
armed = !armed
|
|
|
|
print("Drone armed")
|
|
|
|
elif armed:
|
|
|
|
anim_player.pause()
|
|
|
|
armed = !armed
|
|
|
|
print("Drone disarmed")
|
|
|
|
|
|
|
|
|
2025-02-03 01:00:55 +00:00
|
|
|
func _start_flip_over_timer():
|
|
|
|
if flip_over_timer.time_left > 0:
|
|
|
|
pass
|
|
|
|
elif !can_flip:
|
|
|
|
flip_over_timer.start()
|
|
|
|
|
|
|
|
|
|
|
|
func _on_flip_over_timeout():
|
|
|
|
if flip_over_detection_ray.is_colliding() and flip_over_detection_ray.get_collider().is_in_group("Ground"):
|
|
|
|
can_flip = true
|
|
|
|
input_suggestion_label.text = "press A to flip drone"
|
|
|
|
input_suggestion_label.show()
|
2025-02-04 02:00:37 +00:00
|
|
|
else:
|
|
|
|
input_suggestion_label.hide()
|
2025-02-03 01:00:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
func _handle_drone_flipping():
|
|
|
|
if flip_over_detection_ray.is_colliding() and flip_over_detection_ray.get_collider().is_in_group("Ground"):
|
|
|
|
global_rotation = Vector3.ZERO
|
|
|
|
input_suggestion_label.hide()
|
|
|
|
can_flip = false
|
2025-02-04 02:00:37 +00:00
|
|
|
else:
|
|
|
|
input_suggestion_label.hide()
|
2025-02-03 01:00:55 +00:00
|
|
|
|
|
|
|
|
2025-02-03 04:55:33 +00:00
|
|
|
func _physics_process(_delta): # Still needed for other physics
|
2025-02-03 01:00:55 +00:00
|
|
|
if flip_over_detection_ray.is_colliding() and flip_over_detection_ray.get_collider().is_in_group("Ground"):
|
|
|
|
_start_flip_over_timer()
|
|
|
|
|
|
|
|
if Input.is_action_just_pressed("accept") and can_flip:
|
|
|
|
_handle_drone_flipping()
|
|
|
|
|
|
|
|
|
2025-02-03 04:55:33 +00:00
|
|
|
func _input(event):
|
|
|
|
if Input.is_action_just_pressed("reset_drone"):
|
|
|
|
global_position = reset_point.global_position
|
|
|
|
global_rotation = Vector3.ZERO
|
|
|
|
linear_velocity = Vector3.ZERO
|
|
|
|
angular_velocity = Vector3.ZERO
|
|
|
|
|
|
|
|
|
2025-02-04 02:00:37 +00:00
|
|
|
func _integrate_forces(state):
|
|
|
|
if armed and GameManager.game_started:
|
2025-02-03 01:00:55 +00:00
|
|
|
var yaw_input = Input.get_axis("yaw_right", "yaw_left")
|
|
|
|
var roll_input = Input.get_axis("roll_right", "roll_left")
|
|
|
|
var pitch_input = Input.get_axis("pitch_backward", "pitch_forward")
|
|
|
|
var throttle_input = Input.get_axis("throttle_down", "throttle_up")
|
2025-02-04 02:00:37 +00:00
|
|
|
|
|
|
|
if using_joy_controller:
|
|
|
|
if throttle_input > 0:
|
|
|
|
throttle_speed = throttle_input * 100
|
2025-02-04 03:47:25 +00:00
|
|
|
apply_central_force(global_transform.basis.y * throttle_curve.sample((throttle_speed-1)/99) * thrust_factor)
|
2025-02-04 02:00:37 +00:00
|
|
|
|
|
|
|
linear_velocity.x = clampf(linear_velocity.x, -max_speed, max_speed)
|
2025-02-04 03:47:25 +00:00
|
|
|
linear_velocity.y = clampf(linear_velocity.y, -max_speed*1.5, max_speed)
|
2025-02-04 02:00:37 +00:00
|
|
|
linear_velocity.z = clampf(linear_velocity.z, -max_speed, max_speed)
|
2025-02-04 03:47:25 +00:00
|
|
|
|
|
|
|
apply_central_force(global_transform.basis.y * 1 * thrust_factor) # Base thrust while props are idley spinning
|
2025-02-04 02:00:37 +00:00
|
|
|
|
|
|
|
# Speed scale adjusted for animation
|
|
|
|
anim_player.speed_scale = throttle_input * 4
|
|
|
|
anim_player.speed_scale = clampf(anim_player.speed_scale, 1.0, 4.0)
|
2025-02-03 01:00:55 +00:00
|
|
|
|
|
|
|
if yaw_input != 0:
|
|
|
|
rotate_object_local(Vector3.UP, yaw_input * rotation_speed) # Y axis rotation
|
|
|
|
if roll_input != 0:
|
|
|
|
rotate_object_local(Vector3.FORWARD, roll_input * rotation_speed) # Z axis rotation
|
|
|
|
if pitch_input != 0:
|
|
|
|
rotate_object_local(Vector3.RIGHT, pitch_input * rotation_speed) # X axis rotation
|
|
|
|
|
2025-02-03 04:55:33 +00:00
|
|
|
# Damping
|
2025-02-03 01:00:55 +00:00
|
|
|
if yaw_input == 0:
|
2025-02-04 03:47:25 +00:00
|
|
|
state.angular_velocity.y = lerp(state.angular_velocity.y, 0.0, 0.1)
|
2025-02-03 01:00:55 +00:00
|
|
|
if roll_input == 0:
|
2025-02-04 03:47:25 +00:00
|
|
|
state.angular_velocity.z = lerp(state.angular_velocity.z, 0.0, 0.1)
|
2025-02-03 01:00:55 +00:00
|
|
|
if pitch_input == 0:
|
2025-02-04 03:47:25 +00:00
|
|
|
state.angular_velocity.x = lerp(state.angular_velocity.x, 0.0, 0.1)
|