157 lines
5.8 KiB
GDScript
157 lines
5.8 KiB
GDScript
class_name ViewMovement extends Node3D
|
|
|
|
@export var player: Hero
|
|
|
|
@export_category("Bobbing")
|
|
@export var camera: Camera3D
|
|
@export var focus_raycast: RayCast3D
|
|
@export var enable_head_bob: bool = true
|
|
@export var head_bob_max_effect_speed: float = 4.317
|
|
@export var head_bob_amplitude: float = 0.08
|
|
@export var head_bob_frequency: float = 8.0
|
|
@export var target_stabilisation: bool = false
|
|
|
|
@export_category("Strafe Tilting")
|
|
@export var enable_strafe_tilt: bool = false
|
|
@export var tilt_max_effect_speed: float = 4.317
|
|
@export var tilt_amount_x: float = 0.75
|
|
@export var tilt_amount_y: float = 0.0
|
|
|
|
var sample_point: float = 0.0
|
|
var speed_factor: float = 0.0
|
|
|
|
var trauma: float = 0.0
|
|
var trauma_recovery_speed: float = 0.7
|
|
var camera_shake: float = 0.0
|
|
var noise_sample: float = 0.0
|
|
var shake_speed: float = 50.0
|
|
var max_shake_angle: float = 45.0
|
|
var pitch_noise: FastNoiseLite = FastNoiseLite.new()
|
|
var yaw_noise: FastNoiseLite = FastNoiseLite.new()
|
|
var roll_noise: FastNoiseLite = FastNoiseLite.new()
|
|
var constant_trauma: float = 0.0
|
|
|
|
|
|
func _ready() -> void:
|
|
pitch_noise.noise_type = FastNoiseLite.TYPE_PERLIN
|
|
yaw_noise.noise_type = FastNoiseLite.TYPE_PERLIN
|
|
roll_noise.noise_type = FastNoiseLite.TYPE_PERLIN
|
|
pitch_noise.frequency = 0.03
|
|
yaw_noise.frequency = 0.03
|
|
roll_noise.frequency = 0.01
|
|
var noise_seed: int = randi()
|
|
pitch_noise.seed = noise_seed
|
|
yaw_noise.seed = noise_seed + 1
|
|
roll_noise.seed = noise_seed + 2
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
if enable_head_bob and player.is_on_floor():
|
|
#TODO: maybe make the speed slower/faster on slopes?
|
|
var player_speed: float = Vector2(player.velocity.x, player.velocity.z).length()
|
|
speed_factor = lerp(speed_factor, player_speed / head_bob_max_effect_speed, 20.0 * delta)
|
|
else:
|
|
speed_factor = lerp(speed_factor, 0.0, 20.0 * delta)
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
#trauma = max(0.0, trauma - ((1.0 / trauma_recovery_speed) * delta))
|
|
#camera_shake = pow(max(trauma, constant_trauma), 2.0)
|
|
#noise_sample += shake_speed * delta
|
|
#$Camera3D/ProgressBar.value = max(trauma, constant_trauma) * 100.0
|
|
#$Camera3D/ProgressBar2.value = camera_shake * 100.0
|
|
#if Input.is_action_just_pressed("damage"):
|
|
#add_trauma()
|
|
#if Input.is_action_just_pressed("big_damage"):
|
|
#add_trauma(1.0)
|
|
#if Input.is_action_just_pressed("increase_trauma"):
|
|
#constant_trauma = min(1.0, constant_trauma + 0.1)
|
|
#if Input.is_action_just_pressed("decrease_trauma"):
|
|
#constant_trauma = max(0.0, constant_trauma - 0.1)
|
|
sample_point += delta * head_bob_frequency * speed_factor
|
|
var camera_translation: Vector3 = Vector3.ZERO
|
|
var camera_tilt: Vector3 = Vector3.ZERO
|
|
camera_translation = minecraft_translation(head_bob_amplitude * speed_factor)
|
|
camera_tilt += minecraft_tilt(head_bob_amplitude * speed_factor)
|
|
if target_stabilisation:
|
|
camera.look_at(focus_target())
|
|
if enable_strafe_tilt:
|
|
camera_tilt += get_strafe_tilt(player.velocity)
|
|
#var shake_vector: Vector3 = Vector3.ZERO
|
|
#shake_vector.x = deg_to_rad(pitch_noise.get_noise_1d(noise_sample) * camera_shake * max_shake_angle)
|
|
#shake_vector.y = deg_to_rad(yaw_noise.get_noise_1d(noise_sample) * camera_shake * max_shake_angle)
|
|
#shake_vector.z = deg_to_rad(roll_noise.get_noise_1d(noise_sample) * camera_shake * max_shake_angle)
|
|
#camera_tilt += shake_vector
|
|
camera.rotation = camera_tilt
|
|
translate_camera(camera_translation)
|
|
|
|
|
|
func hfov_to_vfov(hfov_degrees: float) -> void:
|
|
return rad_to_deg(2.0 * atan(tan(deg_to_rad(hfov_degrees) / 2.0) * 9.0 / 16.0))
|
|
|
|
|
|
func minecraft_translation(amplitude: float) -> Vector3:
|
|
return sample_u_shape(sample_point, amplitude, 0.7)
|
|
|
|
|
|
func minecraft_tilt(amplitude: float) -> Vector3:
|
|
var pitch_angle: float = deg_to_rad(5)
|
|
var roll_angle: float = deg_to_rad(2)
|
|
var x: float = -abs(sin(sample_point + (PI / 2))) * pitch_angle * amplitude
|
|
var z: float = sin(sample_point) * roll_angle * amplitude
|
|
return Vector3(x, 0.0, z)
|
|
|
|
|
|
func sample_sine(sample: float, amplitude: float) -> Vector3:
|
|
return Vector3(0.0, sin(sample) * amplitude, 0.0)
|
|
|
|
|
|
func sample_lemniscate(sample: float, amplitude: float, ratio: float = 1.0) -> Vector3:
|
|
var y: float = sin(sample) * amplitude
|
|
var x: float = (cos(sample / 2.0) * amplitude * 2.0) * ratio
|
|
return Vector3(x, y, 0.0)
|
|
|
|
|
|
func sample_u_shape(sample: float, amplitude: float, ratio: float = 1.0) -> Vector3:
|
|
var y: float = ((abs(sin(sample + (PI / 2.0)))) * amplitude) - (amplitude / 2.0)
|
|
var x: float = sin(sample) * amplitude * ratio
|
|
return Vector3(x, y, 0.0)
|
|
|
|
|
|
func translate_camera(offset: Vector3) -> void:
|
|
var target_position: Vector3 = Vector3.ZERO
|
|
target_position += global_transform.basis.x * offset.x
|
|
target_position += Vector3.UP * offset.y
|
|
target_position += global_transform.basis.z * offset.z
|
|
camera.global_position = global_position + target_position
|
|
|
|
|
|
func focus_target() -> Vector3:
|
|
if focus_raycast.is_colliding():
|
|
return focus_raycast.get_collision_point()
|
|
else:
|
|
return focus_raycast.global_position + -focus_raycast.global_transform.basis.z * 30.0
|
|
|
|
|
|
#func tilt_camera(tilt: Vector3, speed: float) -> void:
|
|
##camera.rotation.x = lerp(camera.rotation.x, tilt.x, speed)
|
|
##camera.rotation.y = lerp(camera.rotation.y, tilt.y, speed)
|
|
##camera.rotation.z = lerp(camera.rotation.z, tilt.z, speed)
|
|
#camera.rotation.x = tilt.x
|
|
#camera.rotation.y = tilt.y
|
|
#camera.rotation.z = tilt.z
|
|
|
|
|
|
func get_strafe_tilt(player_velocity: Vector3) -> Vector3:
|
|
var side_dot: float = player_velocity.normalized().dot(-global_transform.basis.z)
|
|
var front_dot: float = player_velocity.normalized().dot(-global_transform.basis.x)
|
|
var speed_factor: float = player_velocity.length() / tilt_max_effect_speed
|
|
var tilt_vector: Vector3 = Vector3.ZERO
|
|
tilt_vector.z = deg_to_rad(tilt_amount_x * front_dot * speed_factor)
|
|
tilt_vector.x = deg_to_rad(tilt_amount_y * -side_dot * speed_factor)
|
|
return tilt_vector
|
|
|
|
|
|
func add_trauma(amount: float = 0.3) -> void:
|
|
trauma = min(1.0, trauma + amount)
|