From 34e20b9e84c4340c5663a408ff2cef388eb0407a Mon Sep 17 00:00:00 2001 From: Holly Date: Tue, 4 Feb 2025 22:32:23 +0000 Subject: [PATCH] did somebody say stairs? --- scenes/world/Player.tscn | 41 +++++++++++++++++++++++- src/Player.gd | 67 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/scenes/world/Player.tscn b/scenes/world/Player.tscn index f3c03b1..414a32e 100644 --- a/scenes/world/Player.tscn +++ b/scenes/world/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=8 format=3 uid="uid://dm33ofcbh8sht"] +[gd_scene load_steps=10 format=3 uid="uid://dm33ofcbh8sht"] [ext_resource type="Script" path="res://src/Player.gd" id="1_n772d"] [ext_resource type="Texture2D" uid="uid://rfpsi4xnxdu" path="res://GFX/BlinkIcon.png" id="2_kjp08"] @@ -10,6 +10,12 @@ [sub_resource type="BoxShape3D" id="BoxShape3D_7hapa"] size = Vector3(1, 2, 1) +[sub_resource type="BoxMesh" id="BoxMesh_vju81"] +size = Vector3(1, 2, 1) + +[sub_resource type="SeparationRayShape3D" id="SeparationRayShape3D_u64q7"] +length = 0.5 + [node name="Player" type="CharacterBody3D"] script = ExtResource("1_n772d") @@ -22,6 +28,39 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.75, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) shape = SubResource("BoxShape3D_7hapa") +[node name="MeshInstance3D" type="MeshInstance3D" parent="Collision"] +visible = false +mesh = SubResource("BoxMesh_vju81") + +[node name="SepRay1" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.5, -0.75) +shape = SubResource("SeparationRayShape3D_u64q7") + +[node name="RayCast3D" type="RayCast3D" parent="SepRay1"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) +enabled = false +target_position = Vector3(0, -0.55, 0) + +[node name="SepRay2" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.5, -0.75) +shape = SubResource("SeparationRayShape3D_u64q7") + +[node name="RayCast3D" type="RayCast3D" parent="SepRay2"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) +enabled = false +target_position = Vector3(0, -0.55, 0) + +[node name="SepRay3" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.5, -0.75) +shape = SubResource("SeparationRayShape3D_u64q7") + +[node name="RayCast3D" type="RayCast3D" parent="SepRay3"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) +enabled = false +target_position = Vector3(0, -0.55, 0) + +[node name="StairRay" type="RayCast3D" parent="."] + [node name="FloorRay" type="RayCast3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) target_position = Vector3(0, -0.1, 0) diff --git a/src/Player.gd b/src/Player.gd index 713a44b..cf543f2 100644 --- a/src/Player.gd +++ b/src/Player.gd @@ -239,8 +239,8 @@ func _process(delta: float) -> void: #print(str(cos(angle) * CurrSpeed * 100000 * Global.FPSfactor), " ", str(sin(angle) * CurrSpeed * 100000 * Global.FPSfactor)) #position.x += cos(angle) * CurrSpeed * 100000 * Global.FPSfactor #position.z += sin(angle) * CurrSpeed * 100000 * Global.FPSfactor - var movementX = (direction.x * CurrSpeed) * 160 * Global.FPSfactor - var movementZ = (direction.z * CurrSpeed) * 160 * Global.FPSfactor + var movementX = (direction.x * CurrSpeed) * 500 * Global.FPSfactor + var movementZ = (direction.z * CurrSpeed) * 500 * Global.FPSfactor #print(CurrSpeed, " ", direction.x, " ", direction.z, " ", str(movementX), " ", str(movementZ)) velocity.x = movementX velocity.z = movementZ @@ -294,10 +294,73 @@ func _process(delta: float) -> void: velocity.y += DropSpeed * Global.FPSfactor if not UnableToMove: + rotateStepSepRay() move_and_slide() + snapDownToFloorCheck() ForceMove = false +@onready var initialSepRayDist = abs($SepRay1.position.z) +const RAY_MOVE_VEC = Vector3(0, 1, 0) +const RAY_MAX_SLOPE_ROT = Vector3(1, 0, 0) +const RAY_ROT_L = deg_to_rad(-50) +const RAY_ROT_R = deg_to_rad(50) +var lastXzVel = Vector3() +func rotateStepSepRay(): + var xzVel = velocity * Vector3(1, 0, 1) + + if xzVel.length() < 0.1: + xzVel = lastXzVel + else: + lastXzVel = xzVel + + var xzFRayPos = xzVel.normalized() * initialSepRayDist + $SepRay1.global_position.x = global_position.x + xzFRayPos.x + $SepRay1.global_position.z = global_position.z + xzFRayPos.z + + var xzLRayPos = xzFRayPos.rotated(RAY_MOVE_VEC, RAY_ROT_L) + $SepRay2.global_position.x = global_position.x + xzLRayPos.x + $SepRay2.global_position.z = global_position.z + xzLRayPos.z + + var xzRRayPos = xzFRayPos.rotated(RAY_MOVE_VEC, RAY_ROT_R) + $SepRay3.global_position.x = global_position.x + xzRRayPos.x + $SepRay3.global_position.z = global_position.z + xzRRayPos.z + + $SepRay1/RayCast3D.force_raycast_update() + $SepRay2/RayCast3D.force_raycast_update() + $SepRay3/RayCast3D.force_raycast_update() + var maxSlopeAngleDot = RAY_MOVE_VEC.rotated(RAY_MAX_SLOPE_ROT, floor_max_angle / 4).dot(RAY_MOVE_VEC) + var isTooSteep = false + if $SepRay1/RayCast3D.is_colliding() and $SepRay1/RayCast3D.get_collision_normal().dot(RAY_MOVE_VEC) < maxSlopeAngleDot: + isTooSteep = true + if $SepRay2/RayCast3D.is_colliding() and $SepRay2/RayCast3D.get_collision_normal().dot(RAY_MOVE_VEC) < maxSlopeAngleDot: + isTooSteep = true + if $SepRay3/RayCast3D.is_colliding() and $SepRay3/RayCast3D.get_collision_normal().dot(RAY_MOVE_VEC) < maxSlopeAngleDot: + isTooSteep = true + + $SepRay1.disabled = isTooSteep + $SepRay2.disabled = isTooSteep + $SepRay3.disabled = isTooSteep + +var wasOnFloorLastFrame = false +var snappedLastFrame = false +func snapDownToFloorCheck(): + var didSnap = false + if not is_on_floor() and velocity.y <= 0 and (wasOnFloorLastFrame or snappedLastFrame) and $StairRay.is_colliding(): + var bodyTestResult = PhysicsTestMotionResult3D.new() + var params = PhysicsTestMotionParameters3D.new() + var maxStepDown = -0.5 + params.from = global_transform + params.motion = Vector3(0, maxStepDown, 0) + if PhysicsServer3D.body_test_motion(get_rid(), params, bodyTestResult): + var travelY = bodyTestResult.get_travel().y; + position.y += travelY + apply_floor_snap() + didSnap = true + + wasOnFloorLastFrame = is_on_floor() + snappedLastFrame = didSnap + func _input(event: InputEvent) -> void: if event is InputEventMouseMotion: Rotation.y -= event.relative.x / 2