Changes to the player
- Made the character inherit from StairsCharacter3D (Plugin) - Made the players head smoothly adjust when stepping. - Reintroduced the previously broken headbobbing. - Adjusted collisions.
This commit is contained in:
parent
31363b1d52
commit
a4100e3026
@ -1,5 +1,5 @@
|
|||||||
class_name Character3D
|
class_name Character3D
|
||||||
extends CharacterBody3D
|
extends StairsCharacter3D
|
||||||
|
|
||||||
@export var movement: CharacterMovement
|
@export var movement: CharacterMovement
|
||||||
@export var speed_scale: float = 1.0
|
@export var speed_scale: float = 1.0
|
||||||
@ -12,11 +12,11 @@ var air_control: float = 1.0
|
|||||||
var freeze_air_control: bool = false
|
var freeze_air_control: bool = false
|
||||||
var last_platform_velocity := Vector3.ZERO
|
var last_platform_velocity := Vector3.ZERO
|
||||||
var _was_on_floor: bool = false
|
var _was_on_floor: bool = false
|
||||||
var _previous_velocity: Vector3
|
var previous_velocity: Vector3
|
||||||
|
|
||||||
|
|
||||||
func move(direction: Vector3, delta: float) -> void:
|
func move(direction: Vector3, delta: float) -> void:
|
||||||
direction *= (speed * speed_scale)
|
direction *= speed * speed_scale
|
||||||
|
|
||||||
var on_floor: bool = is_on_floor()
|
var on_floor: bool = is_on_floor()
|
||||||
|
|
||||||
@ -56,9 +56,9 @@ func move(direction: Vector3, delta: float) -> void:
|
|||||||
velocity = velocity.move_toward(direction, speed_change * delta)
|
velocity = velocity.move_toward(direction, speed_change * delta)
|
||||||
|
|
||||||
await get_tree().physics_frame
|
await get_tree().physics_frame
|
||||||
_previous_velocity = velocity
|
previous_velocity = velocity
|
||||||
#DebugDraw3D.draw_arrow(global_position, global_position + velocity, Color.BLUE, 0.5, true)
|
#DebugDraw3D.draw_arrow(global_position, global_position + velocity, Color.BLUE, 0.5, true)
|
||||||
#SPrint.print_msg("%s Velocity: %s" %[self , velocity], 0.02)
|
#SPrint.print_msg("%s Velocity: %s" % [self , velocity], 0.02)
|
||||||
|
|
||||||
|
|
||||||
## @tutorial: https://gmtk.itch.io/platformer-toolkit/devlog/395523/behind-the-code
|
## @tutorial: https://gmtk.itch.io/platformer-toolkit/devlog/395523/behind-the-code
|
||||||
@ -67,13 +67,13 @@ func apply_gravity(delta: float) -> void:
|
|||||||
var gravity_multiplier: float = 1.0
|
var gravity_multiplier: float = 1.0
|
||||||
|
|
||||||
if velocity.y < -margin:
|
if velocity.y < -margin:
|
||||||
#SPrint.print_msg("Falling\n%s" %velocity.y, 0.02)
|
#SPrint.print_msg("Falling\n%s" % velocity.y, 0.02)
|
||||||
gravity_multiplier = movement.fall_gravity_multiplier
|
gravity_multiplier = movement.fall_gravity_multiplier
|
||||||
elif velocity.y > margin:
|
elif velocity.y > margin:
|
||||||
#SPrint.print_msg("Rising\n%s" %velocity.y, 0.02)
|
#SPrint.print_msg("Rising\n%s" % velocity.y, 0.02)
|
||||||
gravity_multiplier = movement.rise_gravity_multiplier
|
gravity_multiplier = movement.rise_gravity_multiplier
|
||||||
else:
|
else:
|
||||||
#SPrint.print_msg("Peaking\n%s" %velocity.y, 0.02)
|
#SPrint.print_msg("Peaking\n%s" % velocity.y, 0.02)
|
||||||
gravity_multiplier = movement.peak_gravity_multiplier
|
gravity_multiplier = movement.peak_gravity_multiplier
|
||||||
|
|
||||||
velocity.y -= (movement.get_gravity() * gravity_multiplier) * delta
|
velocity.y -= (movement.get_gravity() * gravity_multiplier) * delta
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
class_name GameCamera3D
|
class_name PlayerHead
|
||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
const ACTION_CAMERA_UP: StringName = &"camera_up"
|
const ACTION_CAMERA_UP: StringName = &"camera_up"
|
||||||
@ -38,13 +38,24 @@ const CONTROLLER_INVERT_Y_PATH: StringName = &"game/input/camera_controller_inve
|
|||||||
@export var headbob_frequency: float = 0.5
|
@export var headbob_frequency: float = 0.5
|
||||||
@export var headbob_multiplier: float = 1.0
|
@export var headbob_multiplier: float = 1.0
|
||||||
@export var headbob_character: Character3D
|
@export var headbob_character: Character3D
|
||||||
|
@export var headbob_target: Node3D
|
||||||
|
|
||||||
|
@export_group("Step Smoothing", "step_")
|
||||||
|
@export var step_smoothing_target: Node3D
|
||||||
|
@export var step_speed: float = 8.0
|
||||||
|
|
||||||
var rotational_direction: Vector2
|
var rotational_direction: Vector2
|
||||||
var rotational_velocity: Vector2
|
var rotational_velocity: Vector2
|
||||||
var input_event: InputEvent
|
var input_event: InputEvent
|
||||||
var using_controller: bool = false
|
var using_controller: bool = false
|
||||||
|
# Headbobbing
|
||||||
var headbob_time: float = 0.0
|
var headbob_time: float = 0.0
|
||||||
var headbob_enabled: bool = true
|
var headbob_enabled: bool = true
|
||||||
|
# Stair smooting
|
||||||
|
var stair_camera_offset_height: float = 0.0
|
||||||
|
var _previous_position: Vector3
|
||||||
|
var _stair_camera_target_height: float = 0.0
|
||||||
|
var _stair_camera_step_smoothing: bool = false
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
@ -62,18 +73,23 @@ func _ready() -> void:
|
|||||||
ProjectSettings.settings_changed.connect(_update_settings)
|
ProjectSettings.settings_changed.connect(_update_settings)
|
||||||
_update_settings.call()
|
_update_settings.call()
|
||||||
|
|
||||||
|
_setup_step_smoothing()
|
||||||
|
|
||||||
func _physics_process(delta: float) -> void:
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
if not GameGlobals.in_cutscene:
|
if not GameGlobals.in_cutscene:
|
||||||
_process_input(delta)
|
_process_input(delta)
|
||||||
_perform_head_bob(delta)
|
_perform_head_bob(delta)
|
||||||
|
|
||||||
|
_process_step_smoothing(delta)
|
||||||
|
|
||||||
|
|
||||||
func _unhandled_input(event: InputEvent) -> void:
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
if event is InputEventMouseMotion or event is InputEventJoypadMotion:
|
if event is InputEventMouseMotion or event is InputEventJoypadMotion:
|
||||||
input_event = event
|
input_event = event
|
||||||
|
|
||||||
|
|
||||||
|
#region Mouse/Controller rotation
|
||||||
func apply_rotation(rot: Vector2) -> void:
|
func apply_rotation(rot: Vector2) -> void:
|
||||||
rotate_y(-rot.x)
|
rotate_y(-rot.x)
|
||||||
rotation.x = rotation.x - rot.y
|
rotation.x = rotation.x - rot.y
|
||||||
@ -156,12 +172,14 @@ func _process_controller(delta: float) -> void:
|
|||||||
|
|
||||||
func _lerp_rotational_velocity(sensitivity: float, friction: float, delta: float) -> Vector2:
|
func _lerp_rotational_velocity(sensitivity: float, friction: float, delta: float) -> Vector2:
|
||||||
return rotational_velocity.lerp(rotational_direction * sensitivity, friction * delta)
|
return rotational_velocity.lerp(rotational_direction * sensitivity, friction * delta)
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Headbobbing
|
||||||
func _perform_head_bob(delta: float) -> void:
|
func _perform_head_bob(delta: float) -> void:
|
||||||
if not headbob_enabled:
|
if not headbob_enabled:
|
||||||
camera.position = Vector3.ZERO
|
headbob_target.position = Vector3.ZERO
|
||||||
camera.rotation.z = 0.0
|
headbob_target.rotation.z = 0.0
|
||||||
headbob_time = 0.0
|
headbob_time = 0.0
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -172,7 +190,38 @@ func _perform_head_bob(delta: float) -> void:
|
|||||||
headbob_time += delta * headbob_speed * headbob_multiplier
|
headbob_time += delta * headbob_speed * headbob_multiplier
|
||||||
headbob_time = fposmod(headbob_time, TAU)
|
headbob_time = fposmod(headbob_time, TAU)
|
||||||
|
|
||||||
camera.position.y = sin(headbob_time * headbob_frequency) * headbob_range
|
headbob_target.position.y = sin(headbob_time * headbob_frequency) * headbob_range
|
||||||
camera.position.x = cos(headbob_time * headbob_frequency / 2) * headbob_range
|
headbob_target.position.x = cos(headbob_time * headbob_frequency / 2) * headbob_range
|
||||||
camera.rotation.z = deg_to_rad(lerp(camera.position.x, camera.position.y, 0.5)) * TAU
|
headbob_target.rotation.z = deg_to_rad(lerp(headbob_target.position.x, headbob_target.position.y, 0.5)) * TAU
|
||||||
SPrint.print_msgf(str("Head Z-Rotation: ", camera.rotation.z), true)
|
SPrint.print_msgf(str("Head Z-Rotation: ", headbob_target.rotation.z), true)
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Step Smoothing
|
||||||
|
func smooth_step(height_change: float) -> void:
|
||||||
|
_stair_camera_target_height -= height_change
|
||||||
|
_stair_camera_step_smoothing = true
|
||||||
|
|
||||||
|
|
||||||
|
func _setup_step_smoothing() -> void:
|
||||||
|
headbob_character.on_stair_step.connect(_on_stair_step)
|
||||||
|
stair_camera_offset_height = step_smoothing_target.position.y
|
||||||
|
|
||||||
|
|
||||||
|
func _on_stair_step() -> void:
|
||||||
|
smooth_step(global_position.y - _previous_position.y)
|
||||||
|
|
||||||
|
|
||||||
|
func _process_step_smoothing(delta: float) -> void:
|
||||||
|
if _stair_camera_step_smoothing and is_instance_valid(step_smoothing_target):
|
||||||
|
_stair_camera_target_height = lerp(_stair_camera_target_height, 0.0, step_speed * delta)
|
||||||
|
|
||||||
|
if absf(_stair_camera_target_height) < 0.0025:
|
||||||
|
_stair_camera_target_height = 0.0
|
||||||
|
_stair_camera_step_smoothing = false
|
||||||
|
|
||||||
|
var target_pos := Vector3.UP * (stair_camera_offset_height + _stair_camera_target_height)
|
||||||
|
step_smoothing_target.position = target_pos.rotated(Vector3.LEFT, rotation.x)
|
||||||
|
|
||||||
|
_previous_position = global_position
|
||||||
|
#endregion
|
||||||
|
|||||||
@ -25,9 +25,10 @@ var has_control: bool = true
|
|||||||
var is_crouching: bool = false
|
var is_crouching: bool = false
|
||||||
var crouch_speed_affection: float = 0.0
|
var crouch_speed_affection: float = 0.0
|
||||||
|
|
||||||
@onready var head: GameCamera3D = $Head
|
@onready var head: PlayerHead = $Head
|
||||||
@onready var collision_shape: CollisionShape3D = $CollisionShape3D
|
@onready var collision_shape: CollisionShape3D = $CylinderCollider
|
||||||
@onready var standup_checker: Area3D = $StandupChecker
|
@onready var standup_checker: Area3D = $StandupChecker
|
||||||
|
@onready var stair_stepper: StairStepper = $StairStepper
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
@ -51,12 +52,15 @@ func _physics_process(delta: float) -> void:
|
|||||||
if not is_on_floor():
|
if not is_on_floor():
|
||||||
apply_gravity(delta)
|
apply_gravity(delta)
|
||||||
elif not _was_on_floor:
|
elif not _was_on_floor:
|
||||||
if _previous_velocity.y <= -2.0:
|
if previous_velocity.y <= -2.0:
|
||||||
head.camera.shake(0.025, 0.175)
|
head.camera.shake(0.025, 0.175)
|
||||||
|
|
||||||
if not has_control:
|
if not has_control:
|
||||||
move(Vector3.ZERO, delta)
|
move(Vector3.ZERO, delta)
|
||||||
move_and_slide()
|
move_and_stair_step()
|
||||||
|
|
||||||
|
#if is_on_floor():
|
||||||
|
#stair_stepper.handle_step_climbing()
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle jump.
|
# Handle jump.
|
||||||
@ -78,8 +82,15 @@ func _physics_process(delta: float) -> void:
|
|||||||
speed *= remap(crouch_speed_affection, 0.0, 1.0, 1.0, standup_speed_affection)
|
speed *= remap(crouch_speed_affection, 0.0, 1.0, 1.0, standup_speed_affection)
|
||||||
|
|
||||||
move(movement_direction, delta)
|
move(movement_direction, delta)
|
||||||
|
move_and_stair_step()
|
||||||
|
|
||||||
move_and_slide()
|
SPrint.print_msgf(
|
||||||
|
"Player Horizontal-Velocity: %s\nPlayer Vertical-Velocity: %s"
|
||||||
|
% [(velocity * Utils.VEC3_HOR).length(), velocity.y], true
|
||||||
|
)
|
||||||
|
|
||||||
|
#if is_on_floor():
|
||||||
|
#stair_stepper.handle_step_climbing()
|
||||||
|
|
||||||
|
|
||||||
func apply_gravity(delta: float) -> void:
|
func apply_gravity(delta: float) -> void:
|
||||||
@ -119,4 +130,8 @@ func handle_crouching(delta: float) -> void:
|
|||||||
head.position.y = lerp(head.position.y, target_camera_height, weight)
|
head.position.y = lerp(head.position.y, target_camera_height, weight)
|
||||||
|
|
||||||
crouch_speed_affection = lerp(crouch_speed_affection, float(is_crouching), weight * standup_speed_affection_speed_multiplier if not is_crouching else 1.0)
|
crouch_speed_affection = lerp(crouch_speed_affection, float(is_crouching), weight * standup_speed_affection_speed_multiplier if not is_crouching else 1.0)
|
||||||
SPrint.print_msgf("Crouching Speed Affection: %s\n%s" % [crouch_speed_affection, is_crouching], true)
|
|
||||||
|
if crouch_speed_affection <= 0.05:
|
||||||
|
crouch_speed_affection = 0.0
|
||||||
|
|
||||||
|
SPrint.print_msgf("Crouching Speed Affection: %s\nIs Crouching: %s" % [crouch_speed_affection, is_crouching], true)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=9 format=3 uid="uid://clhy3kiceqf2o"]
|
[gd_scene load_steps=10 format=3 uid="uid://clhy3kiceqf2o"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://day6rhxicaxqf" path="res://src/gameplay/characters/player/player_character.gd" id="1_hqu6r"]
|
[ext_resource type="Script" uid="uid://day6rhxicaxqf" path="res://src/gameplay/characters/player/player_character.gd" id="1_hqu6r"]
|
||||||
[ext_resource type="Script" uid="uid://dsjlv8midt2g2" path="res://src/gameplay/characters/character_movement.gd" id="2_1ixuj"]
|
[ext_resource type="Script" uid="uid://dsjlv8midt2g2" path="res://src/gameplay/characters/character_movement.gd" id="2_1ixuj"]
|
||||||
@ -13,14 +13,24 @@ max_turning_speed = 70.0
|
|||||||
peak_gravity_multiplier = 0.3
|
peak_gravity_multiplier = 0.3
|
||||||
metadata/_custom_type_script = "uid://dsjlv8midt2g2"
|
metadata/_custom_type_script = "uid://dsjlv8midt2g2"
|
||||||
|
|
||||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_fjt7c"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_bdj5f"]
|
||||||
|
margin = 0.01
|
||||||
|
radius = 0.46
|
||||||
height = 1.8
|
height = 1.8
|
||||||
|
|
||||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_gy1j0"]
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_bdj5f"]
|
||||||
height = 1.59
|
margin = 0.01
|
||||||
radius = 0.49
|
height = 1.8
|
||||||
|
radius = 0.46
|
||||||
|
|
||||||
[node name="PlayerCharacter" type="CharacterBody3D"]
|
[sub_resource type="CylinderShape3D" id="CylinderShape3D_ntkcp"]
|
||||||
|
height = 1.59
|
||||||
|
radius = 0.45
|
||||||
|
|
||||||
|
[node name="PlayerCharacter" type="StairsCharacter3D"]
|
||||||
|
collider = NodePath("CylinderCollider")
|
||||||
|
step_height_up = 0.7
|
||||||
|
step_height_down = 0.7
|
||||||
collision_layer = 2
|
collision_layer = 2
|
||||||
script = ExtResource("1_hqu6r")
|
script = ExtResource("1_hqu6r")
|
||||||
standup_speed_affection = 0.15
|
standup_speed_affection = 0.15
|
||||||
@ -28,30 +38,43 @@ standup_speed_affection_speed_multiplier = 0.5
|
|||||||
movement = SubResource("Resource_vq0uu")
|
movement = SubResource("Resource_vq0uu")
|
||||||
metadata/_custom_type_script = "uid://day6rhxicaxqf"
|
metadata/_custom_type_script = "uid://day6rhxicaxqf"
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CapsuleCollider" type="CollisionShape3D" parent="."]
|
||||||
|
process_mode = 4
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
|
||||||
shape = SubResource("CylinderShape3D_fjt7c")
|
visible = false
|
||||||
|
shape = SubResource("CapsuleShape3D_bdj5f")
|
||||||
|
disabled = true
|
||||||
|
|
||||||
[node name="Head" type="Node3D" parent="." node_paths=PackedStringArray("camera", "headbob_character")]
|
[node name="CylinderCollider" type="CollisionShape3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
|
||||||
|
shape = SubResource("CylinderShape3D_bdj5f")
|
||||||
|
|
||||||
|
[node name="Head" type="Node3D" parent="." node_paths=PackedStringArray("camera", "headbob_character", "headbob_target", "step_smoothing_target")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
|
||||||
script = ExtResource("2_fjt7c")
|
script = ExtResource("2_fjt7c")
|
||||||
camera = NodePath("ShakingCamera")
|
camera = NodePath("Headbobbing/StairStepping/ShakingCamera")
|
||||||
headbob_range = 0.05
|
headbob_range = 0.05
|
||||||
headbob_frequency = 2.0
|
headbob_frequency = 2.0
|
||||||
headbob_character = NodePath("..")
|
headbob_character = NodePath("..")
|
||||||
|
headbob_target = NodePath("Headbobbing")
|
||||||
|
step_smoothing_target = NodePath("Headbobbing/StairStepping")
|
||||||
|
|
||||||
[node name="ShakingCamera" type="Camera3D" parent="Head"]
|
[node name="Headbobbing" type="Node3D" parent="Head"]
|
||||||
|
|
||||||
|
[node name="StairStepping" type="Node3D" parent="Head/Headbobbing"]
|
||||||
|
|
||||||
|
[node name="ShakingCamera" type="Camera3D" parent="Head/Headbobbing/StairStepping"]
|
||||||
|
current = true
|
||||||
fov = 85.0
|
fov = 85.0
|
||||||
script = ExtResource("4_ci1ud")
|
script = ExtResource("4_ci1ud")
|
||||||
metadata/_custom_type_script = "uid://44s0v8mukxk4"
|
metadata/_custom_type_script = "uid://44s0v8mukxk4"
|
||||||
|
|
||||||
[node name="FootstepComponent" type="Node" parent="." node_paths=PackedStringArray("character")]
|
|
||||||
script = ExtResource("4_vq0uu")
|
|
||||||
character = NodePath("..")
|
|
||||||
|
|
||||||
[node name="StandupChecker" type="Area3D" parent="."]
|
[node name="StandupChecker" type="Area3D" parent="."]
|
||||||
input_ray_pickable = false
|
input_ray_pickable = false
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="StandupChecker"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="StandupChecker"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.99, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.99, 0)
|
||||||
shape = SubResource("CylinderShape3D_gy1j0")
|
shape = SubResource("CylinderShape3D_ntkcp")
|
||||||
|
|
||||||
|
[node name="FootstepComponent" type="Node" parent="."]
|
||||||
|
script = ExtResource("4_vq0uu")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user