94 lines
3.0 KiB
GDScript
94 lines
3.0 KiB
GDScript
extends RigidBody3D
|
|
|
|
class_name Dart
|
|
|
|
|
|
|
|
var dragging: bool = false
|
|
var drag_plane: Plane
|
|
var drag_offset: Vector3 = Vector3.ZERO
|
|
var target_pos: Vector3 = Vector3.ZERO
|
|
|
|
# velocity tracking for release throw
|
|
var position_history: Array[Vector3] = []
|
|
var time_history: Array[float] = []
|
|
const HISTORY_LENGTH = 5
|
|
|
|
# drag "stiffness" tuning
|
|
@export var drag_follow_speed: float = 20.0 # how fast it chases the mouse
|
|
@export var max_drag_speed: float = 15.0 # clamp so it doesn't go insane
|
|
@export_range(-180,180) var angle_of_plane: float = 15.0
|
|
|
|
func start_drag(camera: Camera3D, mouse_pos: Vector2, hit_point: Vector3):
|
|
dragging = true
|
|
|
|
# keep it physics-active — don't freeze
|
|
gravity_scale = 1.0 # optional: ignore gravity while held so it doesn't sag
|
|
linear_damp = 4.0 # optional: a bit of damping for stability while dragged
|
|
|
|
#drag_plane = Plane(camera.global_transform.basis.z, hit_point)
|
|
var base_normal = camera.global_transform.basis.z
|
|
var tilt = base_normal.rotated(camera.global_transform.basis.x, deg_to_rad(angle_of_plane)) # tilt adjustable around camera's right axis
|
|
drag_plane = Plane(tilt.normalized(), hit_point)
|
|
drag_offset = global_position - hit_point
|
|
|
|
position_history.clear()
|
|
time_history.clear()
|
|
|
|
func update_drag(camera: Camera3D, mouse_pos: Vector2):
|
|
if not dragging:
|
|
return
|
|
|
|
var ray_origin = camera.project_ray_origin(mouse_pos)
|
|
var ray_dir = camera.project_ray_normal(mouse_pos)
|
|
|
|
var intersection = drag_plane.intersects_ray(ray_origin, ray_dir)
|
|
if intersection:
|
|
target_pos = intersection + drag_offset
|
|
|
|
func _physics_process(delta):
|
|
if dragging:
|
|
# chase the target position with velocity instead of teleporting
|
|
var to_target = target_pos - global_position
|
|
var desired_velocity = to_target * drag_follow_speed
|
|
|
|
if desired_velocity.length() > max_drag_speed:
|
|
desired_velocity = desired_velocity.normalized() * max_drag_speed
|
|
|
|
linear_velocity = desired_velocity
|
|
angular_velocity = angular_velocity.lerp(Vector3.ZERO, 0.2) # optional: damp spin while dragging
|
|
|
|
# track actual position for momentum calc on release
|
|
position_history.append(global_position)
|
|
time_history.append(Time.get_ticks_msec() / 1000.0)
|
|
if position_history.size() > HISTORY_LENGTH:
|
|
position_history.pop_front()
|
|
time_history.pop_front()
|
|
|
|
func release_drag():
|
|
if not dragging:
|
|
return
|
|
dragging = false
|
|
|
|
gravity_scale = 2
|
|
linear_damp = 1.0 # reset to whatever your normal dart damping is
|
|
|
|
var velocity = calculate_throw_velocity() * 1.0
|
|
linear_velocity = velocity
|
|
# angular_velocity left as-is from physics, or compute your own spin here
|
|
|
|
func calculate_throw_velocity() -> Vector3:
|
|
if position_history.size() < 2:
|
|
return linear_velocity # fallback to whatever physics already had
|
|
|
|
var start_pos = position_history[0]
|
|
var end_pos = position_history[position_history.size() - 1]
|
|
var start_time = time_history[0]
|
|
var end_time = time_history[time_history.size() - 1]
|
|
|
|
var dt = end_time - start_time
|
|
if dt <= 0.0:
|
|
return linear_velocity
|
|
|
|
return (end_pos - start_pos) / dt
|