121 lines
3.3 KiB
GDScript
121 lines
3.3 KiB
GDScript
class_name Mech extends Node3D
|
|
|
|
@export_group("Skeleton")
|
|
@export var _skeleton: Skeleton3D
|
|
@export var _pelvis_attachment: BoneAttachment3D
|
|
|
|
@export_subgroup("Left")
|
|
@export var _ankle_bone_l: String = "Ankle_L"
|
|
@export var _leg_ik_l: SkeletonIK3D
|
|
@export var _leg_foot_body_l: CharacterBody3D
|
|
@export var _leg_ik_target_l: Node3D
|
|
@export var _leg_ik_magnet_l: Node3D
|
|
|
|
@export_subgroup("Right")
|
|
@export var _ankle_bone_r: String = "Ankle_R"
|
|
@export var _leg_ik_r: SkeletonIK3D
|
|
@export var _leg_foot_body_r: CharacterBody3D
|
|
@export var _leg_ik_target_r: Node3D
|
|
@export var _leg_ik_magnet_r: Node3D
|
|
|
|
@export_group("Physics")
|
|
@export var _foot_fall_acceleration: float = 1
|
|
|
|
@export_group("Walking")
|
|
@export var _mouse_walk_sensitivity: float = 1
|
|
|
|
var _mouse_relative: Vector2
|
|
var _is_moving_leg_l: bool
|
|
var _is_moving_leg_r: bool
|
|
|
|
|
|
func _ready() -> void:
|
|
_leg_ik_l.start()
|
|
_leg_ik_r.start()
|
|
_ready_leg_ik(_leg_foot_body_l, _ankle_bone_l)
|
|
_ready_leg_ik(_leg_foot_body_r, _ankle_bone_r)
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
_process_leg_ik(_leg_ik_l, _leg_ik_magnet_l)
|
|
_process_leg_ik(_leg_ik_r, _leg_ik_magnet_r)
|
|
_process_position()
|
|
Debugger.text("_is_moving_leg_l", _is_moving_leg_l, 2)
|
|
Debugger.text("_is_moving_leg_r", _is_moving_leg_r, 2)
|
|
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
if _is_moving_leg_l:
|
|
_handle_leg_moving(_mouse_relative, _leg_foot_body_l)
|
|
else:
|
|
_handle_leg_physics(_leg_foot_body_l)
|
|
|
|
if _is_moving_leg_r:
|
|
_handle_leg_moving(_mouse_relative, _leg_foot_body_r)
|
|
else:
|
|
_handle_leg_physics(_leg_foot_body_r)
|
|
|
|
_mouse_relative = Vector2.ZERO
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseMotion:
|
|
var event_mouse := event as InputEventMouseMotion
|
|
_mouse_relative = event_mouse.screen_relative
|
|
else:
|
|
_mouse_relative = Vector2.ZERO
|
|
|
|
if event is InputEventMouseButton:
|
|
var event_mouse := event as InputEventMouseButton
|
|
if event_mouse.is_pressed():
|
|
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
|
else:
|
|
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
|
|
|
if event_mouse.button_index == MOUSE_BUTTON_LEFT:
|
|
_is_moving_leg_l = event_mouse.is_pressed()
|
|
if event_mouse.button_index == MOUSE_BUTTON_RIGHT:
|
|
_is_moving_leg_r = event_mouse.is_pressed()
|
|
|
|
|
|
func _ready_leg_ik(foot_body: Node3D, bone: String) -> void:
|
|
foot_body.position = (
|
|
_skeleton.get_bone_global_rest(_skeleton.find_bone(bone)).origin
|
|
)
|
|
|
|
|
|
func _process_leg_ik(ik: SkeletonIK3D, ik_magnet: Node3D) -> void:
|
|
ik.magnet = to_local(ik_magnet.global_position)
|
|
|
|
|
|
func _process_position() -> void:
|
|
var leg_target_pos_l := _leg_ik_target_l.global_position
|
|
var leg_target_pos_r := _leg_ik_target_r.global_position
|
|
|
|
var root_position := _pelvis_attachment.global_position
|
|
root_position.y = minf(leg_target_pos_l.y, leg_target_pos_r.y)
|
|
|
|
global_position = root_position
|
|
|
|
|
|
func _handle_leg_moving(mouse_delta: Vector2, foot_body: CharacterBody3D) -> void:
|
|
var velocity_local := Vector3(
|
|
0,
|
|
-mouse_delta.y * _mouse_walk_sensitivity,
|
|
mouse_delta.x * _mouse_walk_sensitivity
|
|
)
|
|
foot_body.velocity = transform.basis * velocity_local
|
|
foot_body.move_and_slide()
|
|
foot_body.velocity = Vector3.ZERO
|
|
|
|
|
|
func _handle_leg_physics(foot_body: CharacterBody3D) -> void:
|
|
if foot_body.is_on_floor():
|
|
foot_body.velocity = Vector3.ZERO
|
|
return
|
|
|
|
foot_body.velocity.x = 0
|
|
foot_body.velocity.z = 0
|
|
foot_body.velocity.y -= _foot_fall_acceleration
|
|
foot_body.move_and_slide()
|