diff --git a/client/Main.tscn b/client/Main.tscn index 31798f5..2f29395 100644 --- a/client/Main.tscn +++ b/client/Main.tscn @@ -140,6 +140,7 @@ scale_max = 1.1 tilt = 0.15 [node name="Enemies" type="Node3D" parent="World"] +visible = false script = ExtResource("15_25nmg") scene = ExtResource("15_hgl78") noise = SubResource("FastNoiseLite_yp2fx") diff --git a/client/player/Player.tscn b/client/player/Player.tscn index 50674a9..86615a2 100644 --- a/client/player/Player.tscn +++ b/client/player/Player.tscn @@ -90,6 +90,7 @@ bone_idx = 12 [node name="Weapon" type="BoneAttachment3D" parent="Model/Female/Armature/GeneralSkeleton" index="6"] transform = Transform3D(0, -1, 0, 0, 0, -1, 1, 0, 0, -0.609469, 1.26691, -0.0234125) +visible = false bone_name = "RightMiddleProximal" bone_idx = 44 @@ -124,6 +125,7 @@ libraries = { skeleton = NodePath("../Model/Female/Armature/GeneralSkeleton") movement = NodePath("../Movement") footsteps = SubResource("AudioStreamRandomizer_4yj1k") +step_threshold = 0.1 [node name="Health" parent="." instance=ExtResource("2_np5ag")] max_value = 100.0 diff --git a/client/player/footsteps/Foot.gd b/client/player/footsteps/Foot.gd index 05f1930..e1a1e70 100644 --- a/client/player/footsteps/Foot.gd +++ b/client/player/footsteps/Foot.gd @@ -5,4 +5,6 @@ var bone_id: int var audio: AudioStreamPlayer3D var position: Vector3 var velocity: Vector3 -var attachment: BoneAttachment3D \ No newline at end of file +var attachment: BoneAttachment3D +var floor_distance: float +var normal: Vector3 \ No newline at end of file diff --git a/client/player/footsteps/FootstepsComponent.gd b/client/player/footsteps/FootstepsComponent.gd index 7bcc0b0..a94d79c 100644 --- a/client/player/footsteps/FootstepsComponent.gd +++ b/client/player/footsteps/FootstepsComponent.gd @@ -1,14 +1,17 @@ class_name FootstepsComponent -extends Node +extends Node3D @export var skeleton: Skeleton3D @export var movement: MovementComponent @export var footsteps: AudioStreamRandomizer @export var step_threshold := 0.1 +@export var ik_step_threshold := 0.2 +@export var ik_speed := 5.0 const feet_names := ["LeftFoot", "RightFoot"] var feet: Array[Foot] = [] +var ik_time: float func _ready(): for foot_name in feet_names: @@ -17,6 +20,8 @@ func _ready(): foot.bone_id = skeleton.find_bone(foot_name) foot.audio = get_node(foot_name) foot.position = skeleton.to_global(skeleton.get_bone_global_pose(foot.bone_id).origin) + foot.floor_distance = INF + foot.normal = Vector3.UP foot.attachment = BoneAttachment3D.new() foot.attachment.bone_name = foot_name foot.attachment.bone_idx = foot.bone_id @@ -26,13 +31,25 @@ func _ready(): func _process(delta: float): for foot in feet: + var global_pose := skeleton.get_bone_global_pose(foot.bone_id) var old_position := foot.position - foot.position = skeleton.to_global(skeleton.get_bone_global_pose(foot.bone_id).origin) - foot.velocity = (foot.position - old_position) / delta + foot.position = skeleton.to_global(global_pose.origin) + + if foot.floor_distance < ik_step_threshold: + var bone_to_global := skeleton.global_transform * global_pose + var normal_local := bone_to_global.basis.transposed() * foot.normal + var pose := skeleton.get_bone_pose(foot.bone_id) + var rot := get_foot_rotation(pose.basis, normal_local) + ik_time = minf(ik_time + ik_speed * delta, 1.0) + skeleton.set_bone_pose_rotation(foot.bone_id, pose.basis.slerp(rot, ik_time)) + else: + ik_time = 0 - if foot.position.y > step_threshold: + if foot.floor_distance > step_threshold: continue + foot.velocity = (foot.position - old_position) / delta + if foot.velocity.y > 0: continue @@ -44,6 +61,51 @@ func _process(delta: float): play(foot.audio) +func _physics_process(_delta): + var space_state = get_world_3d().direct_space_state + + for foot in feet: + var from := foot.position + var to := foot.position + Vector3(0, -10, 0) + var query = PhysicsRayQueryParameters3D.create(from, to, 1) + var result = space_state.intersect_ray(query) + + if result: + foot.floor_distance = (foot.position - result.position).length() + foot.normal = result.normal + else: + foot.floor_distance = INF + foot.normal = Vector3.UP + func play(audio_player: AudioStreamPlayer3D): audio_player.stream = footsteps audio_player.play() + +func get_foot_rotation(base: Basis, normal: Vector3) -> Basis: + var rot := align_with_y(base, normal) + return rot.rotated(Vector3.UP, PI) + +func align_with_y(base: Basis, normal: Vector3) -> Basis: + base.x = -base.z.cross(normal) + base.y = normal + return base.orthonormalized() + +# func get_foot_rotation2(base: Basis, normal: Vector3) -> Basis: +# normal.x = -normal.x +# normal.z = -normal.z +# return align_up(base, normal) + +# func align_up(base: Basis, normal: Vector3) -> Basis: +# var result = Basis() +# var node_scale = base.get_scale().abs() + +# result.x = normal.cross(base.z) +# result.y = normal +# result.z = base.x.cross(normal) + +# result = result.orthonormalized() +# result.x *= node_scale.x +# result.y *= node_scale.y +# result.z *= node_scale.z + +# return result diff --git a/client/player/footsteps/FootstepsComponent.tscn b/client/player/footsteps/FootstepsComponent.tscn index 70db607..9d59241 100644 --- a/client/player/footsteps/FootstepsComponent.tscn +++ b/client/player/footsteps/FootstepsComponent.tscn @@ -2,7 +2,7 @@ [ext_resource type="Script" path="res://player/footsteps/FootstepsComponent.gd" id="1_xjrot"] -[node name="Footsteps" type="Node"] +[node name="Footsteps" type="Node3D"] script = ExtResource("1_xjrot") [node name="LeftFoot" type="AudioStreamPlayer3D" parent="."]