HQA_GD/addons/Basic FPS Player/Src/basic_player_startup.gd

172 lines
5.1 KiB
GDScript

@tool
extends CharacterBody3D
var BasicFPSPlayerScene : PackedScene = preload("basic_player_head.tscn")
var addedHead = false
func _enter_tree():
if find_child("Head"):
addedHead = true
if Engine.is_editor_hint() && !addedHead:
var s = BasicFPSPlayerScene.instantiate()
add_child(s)
s.owner = get_tree().edited_scene_root
addedHead = true
## PLAYER MOVMENT SCRIPT ##
###########################
@export_category("Mouse Capture")
@export var CAPTURE_ON_START := true
@export_category("Movement")
@export_subgroup("Settings")
@export var SPEED := 5.0
@export var ACCEL := 50.0
@export var IN_AIR_SPEED := 3.0
@export var IN_AIR_ACCEL := 5.0
@export var JUMP_VELOCITY := 4.5
@export_subgroup("Head Bob")
@export var HEAD_BOB := true
@export var HEAD_BOB_FREQUENCY := 0.3
@export var HEAD_BOB_AMPLITUDE := 0.01
@export_subgroup("Clamp Head Rotation")
@export var CLAMP_HEAD_ROTATION := true
@export var CLAMP_HEAD_ROTATION_MIN := -90.0
@export var CLAMP_HEAD_ROTATION_MAX := 90.0
@export_category("Key Binds")
@export_subgroup("Mouse")
@export var MOUSE_ACCEL := true
@export var KEY_BIND_MOUSE_SENS := 0.005
@export var KEY_BIND_MOUSE_ACCEL := 50
@export_subgroup("Movement")
@export var KEY_BIND_UP := "ui_up"
@export var KEY_BIND_LEFT := "ui_left"
@export var KEY_BIND_RIGHT := "ui_right"
@export var KEY_BIND_DOWN := "ui_down"
@export var KEY_BIND_JUMP := "ui_accept"
@export_category("Advanced")
@export var UPDATE_PLAYER_ON_PHYS_STEP := true # When check player is moved and rotated in _physics_process (fixed fps)
# Otherwise player is updated in _process (uncapped)
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
# To keep track of current speed and acceleration
var speed = SPEED
var accel = ACCEL
# Used when lerping rotation to reduce stuttering when moving the mouse
var rotation_target_player : float
var rotation_target_head : float
# Used when bobing head
var head_start_pos : Vector3
# Current player tick, used in head bob calculation
var tick = 0
func _ready():
if Engine.is_editor_hint():
return
# Capture mouse if set to true
if CAPTURE_ON_START:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
head_start_pos = $Head.position
func _physics_process(delta):
if Engine.is_editor_hint():
return
# Increment player tick, used in head bob motion
tick += 1
if UPDATE_PLAYER_ON_PHYS_STEP:
move_player(delta)
rotate_player(delta)
if HEAD_BOB:
# Only move head when on the floor and moving
if velocity && is_on_floor():
head_bob_motion()
reset_head_bob(delta)
func _process(delta):
if Engine.is_editor_hint():
return
if !UPDATE_PLAYER_ON_PHYS_STEP:
move_player(delta)
rotate_player(delta)
func _input(event):
if Engine.is_editor_hint():
return
# Listen for mouse movement and check if mouse is captured
if event is InputEventMouseMotion && Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
set_rotation_target(event.relative)
func set_rotation_target(mouse_motion : Vector2):
# Add player target to the mouse -x input
rotation_target_player += -mouse_motion.x * KEY_BIND_MOUSE_SENS
# Add head target to the mouse -y input
rotation_target_head += -mouse_motion.y * KEY_BIND_MOUSE_SENS
# Clamp rotation
if CLAMP_HEAD_ROTATION:
rotation_target_head = clamp(rotation_target_head, deg_to_rad(CLAMP_HEAD_ROTATION_MIN), deg_to_rad(CLAMP_HEAD_ROTATION_MAX))
func rotate_player(delta):
if MOUSE_ACCEL:
# Shperical lerp between player rotation and target
quaternion = quaternion.slerp(Quaternion(Vector3.UP, rotation_target_player), KEY_BIND_MOUSE_ACCEL * delta)
# Same again for head
$Head.quaternion = $Head.quaternion.slerp(Quaternion(Vector3.RIGHT, rotation_target_head), KEY_BIND_MOUSE_ACCEL * delta)
else:
# If mouse accel is turned off, simply set to target
quaternion = Quaternion(Vector3.UP, rotation_target_player)
$Head.quaternion = Quaternion(Vector3.RIGHT, rotation_target_head)
func move_player(delta):
# Check if not on floor
if not is_on_floor():
# Reduce speed and accel
speed = IN_AIR_SPEED
accel = IN_AIR_ACCEL
# Add the gravity
velocity.y -= gravity * delta
else:
# Set speed and accel to defualt
speed = SPEED
accel = ACCEL
# Handle Jump.
if Input.is_action_just_pressed(KEY_BIND_JUMP) and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get the input direction and handle the movement/deceleration.
var input_dir = Input.get_vector(KEY_BIND_LEFT, KEY_BIND_RIGHT, KEY_BIND_UP, KEY_BIND_DOWN)
var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
velocity.x = move_toward(velocity.x, direction.x * speed, accel * delta)
velocity.z = move_toward(velocity.z, direction.z * speed, accel * delta)
move_and_slide()
func head_bob_motion():
var pos = Vector3.ZERO
pos.y += sin(tick * HEAD_BOB_FREQUENCY) * HEAD_BOB_AMPLITUDE
pos.x += cos(tick * HEAD_BOB_FREQUENCY/2) * HEAD_BOB_AMPLITUDE * 2
$Head.position += pos
func reset_head_bob(delta):
# Lerp back to the staring position
if $Head.position == head_start_pos:
pass
$Head.position = lerp($Head.position, head_start_pos, 2 * (1/HEAD_BOB_FREQUENCY) * delta)