generated from krampus/template-godot4
All checks were successful
linting & formatting / build (push) Successful in 12s
60 lines
1.5 KiB
GDScript
60 lines
1.5 KiB
GDScript
extends Node3D
|
|
## Give the camera a little kick when the player falls, proportional to landing velocity
|
|
|
|
@export var enabled := true
|
|
@export var character: CharacterBody3D
|
|
|
|
## Minimum landing speed before kick is applied, in m/s
|
|
@export var min_landing_speed := 4.0
|
|
|
|
## How far the camera gets pitched on kick in degrees per m/s of landing velocity
|
|
@export var angle_curve: Curve
|
|
|
|
## How far down the camera gets kicked in meters per m/s of landing velocity
|
|
@export var offset_curve: Curve
|
|
|
|
## How long the rebound takes in seconds per m/s of landing velocity
|
|
@export var rebound_time_curve: Curve
|
|
|
|
var _last_speed := 0.0
|
|
var _in_air := false
|
|
var _tween: Tween
|
|
|
|
|
|
func _get_tween() -> Tween:
|
|
if _tween and _tween.is_valid():
|
|
_tween.kill()
|
|
_tween = create_tween()
|
|
return _tween
|
|
|
|
|
|
func do_kick(landing_speed: float) -> void:
|
|
if landing_speed < min_landing_speed:
|
|
return
|
|
|
|
# Initial kick
|
|
rotation.x = -deg_to_rad(angle_curve.sample(landing_speed))
|
|
position.y = -offset_curve.sample(landing_speed)
|
|
|
|
# Rebound
|
|
var rebound_time := rebound_time_curve.sample(landing_speed)
|
|
var tween := _get_tween()
|
|
tween.set_parallel(true)
|
|
tween.tween_property(self, "rotation:x", 0, rebound_time).set_trans(Tween.TRANS_CUBIC).set_ease(
|
|
Tween.EASE_OUT
|
|
)
|
|
tween.tween_property(self, "position:y", 0, rebound_time).set_trans(Tween.TRANS_CUBIC).set_ease(
|
|
Tween.EASE_OUT
|
|
)
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
if character.is_on_floor():
|
|
if _in_air:
|
|
# First frame after land
|
|
do_kick(absf(_last_speed))
|
|
_in_air = false
|
|
else:
|
|
_in_air = true
|
|
_last_speed = character.velocity.y
|