Files

115 lines
4.7 KiB
GDScript
Raw Permalink Normal View History

2026-07-21 00:27:17 +07:00
extends Node3D
#class name
class_name CameraObject
@export_group("Camera variables")
@export_range(0.0, 5.0, 0.01) var XAxisSens : float
@export_range(0.0, 5.0, 0.01) var YAxisSens : float
@export var maxUpAngleView : float
@export var maxDownAngleView : float
@export_group("FOV variables")
@export var startFOV : float
@export var runFOV : float
@export var fovTransitionSpeed : float
@export_group("Movement changes variables")
@export var baseCamAngle : float
@export var crouchCamAngle : float
@export var baseCameraLerpSpeed : float
@export var crouchCameraLerpSpeed : float
@export var crouchCameraDepth : float
@export_group("Camera bob variables")
@export var enableBob : bool = true
var headBobValue : float
@export var bobFrequency : float
@export var bobAmplitude : float
@export_group("Camera tilt variables")
@export var enableTilt : bool = true
@export var tiltRotationValue : float
@export var tiltRotationSpeed : float
@export var inAirTiltValDivider : float
@export_group("Input variables")
var mouseInput : Vector2
@export var mouseInputSpeed : float
var playCharInputDir : Vector2
#Mouse variables
var mouseFree : bool = false
@export_group("Keybind variables")
@export var mouseModeAction : String = ""
#References variables
@onready var camera : Camera3D = %Camera
@onready var playChar : PlayerCharacter = $".."
@onready var weaponManager : Node3D = %WeaponManager
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) #set mouse as captured
func _unhandled_input(event):
#this function manage camera rotation (360 on x axis, blocked at <= -60 and >= 60 on y axis, to not having the character do a complete head turn, which will be kinda weird)
if event is InputEventMouseMotion:
rotate_y(-event.relative.x * (XAxisSens / 10))
camera.rotate_x(-event.relative.y * (YAxisSens / 10))
camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(maxUpAngleView), deg_to_rad(maxDownAngleView))
mouseInput = event.relative #get position of the mouse in a 2D sceen, so save it in a Vector2
func _process(delta):
applies(delta)
cameraBob(delta)
cameraTilt(delta)
func applies(delta : float):
#manage the differents camera modifications relative to a specific state, except for the FOV
if playChar.stateMachine.currStateName == "Crouch":
position.y = lerp(position.y, 0.715 + crouchCameraDepth, crouchCameraLerpSpeed * delta)
rotation.z = lerp(rotation.z, deg_to_rad(crouchCamAngle) * playChar.inputDirection.x if playChar.inputDirection.x != 0.0 else deg_to_rad(crouchCamAngle), crouchCameraLerpSpeed * delta)
elif playChar.stateMachine.currStateName == "Run":
camera.fov = lerp(camera.fov, runFOV, fovTransitionSpeed * delta)
rotation.z = lerp(rotation.z, deg_to_rad(baseCamAngle), baseCameraLerpSpeed * delta)
elif playChar.stateMachine.currStateName == "Jump":
# Maintain the current FOV when jumping
camera.fov = lerp(camera.fov, camera.fov, fovTransitionSpeed * delta)
elif playChar.stateMachine.currStateName == "Inair":
# Maintain the current FOV when in air
camera.fov = lerp(camera.fov, camera.fov, fovTransitionSpeed * delta)
else:
position.y = lerp(position.y, 0.715, baseCameraLerpSpeed * delta)
rotation.z = lerp(rotation.z, deg_to_rad(baseCamAngle), baseCameraLerpSpeed * delta)
camera.fov = lerp(camera.fov, startFOV, fovTransitionSpeed * delta)
func cameraBob(delta):
if enableBob:
headBobValue += delta * playChar.velocity.length() * float(playChar.is_on_floor())
camera.transform.origin = headbob(headBobValue, bobFrequency, bobAmplitude)
func headbob(time, bobFreq, bobAmpli):
#some trigonometry stuff here, basically it uses the cosinus and sinus functions (sinusoidal function) to get a nice and smooth bob effect
var pos = Vector3.ZERO
pos.y = sin(time * bobFreq) * bobAmpli
pos.x = cos(time * bobFreq / 2) * bobAmpli
return pos
func cameraTilt(delta):
if enableTilt:
#this function manage the camera tilting when the character is moving on the x axis (left and right)
if playChar.moveDirection != Vector3.ZERO and playChar.inputDirection != Vector2.ZERO:
playCharInputDir = playChar.inputDirection #get input direction to know where the character is heading to
#apply smooth tilt movement
if !playChar.is_on_floor(): rotation.z = lerp(rotation.z, -playCharInputDir.x * tiltRotationValue/inAirTiltValDivider, tiltRotationSpeed * delta)
else: rotation.z = lerp(rotation.z, -playCharInputDir.x * tiltRotationValue, tiltRotationSpeed * delta)
func mouseMode():
#manage the mouse mode (visible = can use mouse on the screen, captured = mouse not visible and locked in at the center of the screen)
if Input.is_action_just_pressed(mouseModeAction): mouseFree = !mouseFree
if !mouseFree: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
else: Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)