mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 15:00:09 +01:00
This provides mouse sensitivity that is independent of the viewport size, without needing to query for project settings. This also inverts the mouse motion direction in the 3D navigation demo to better match expectations, and increases mouse sensitivity in the Window Management demo to be closer to other demos.
225 lines
6.1 KiB
GDScript
225 lines
6.1 KiB
GDScript
extends CharacterBody3D
|
|
|
|
# Walking variables.
|
|
const norm_grav = -38.8
|
|
const MAX_SPEED = 22
|
|
const JUMP_SPEED = 26
|
|
const ACCEL = 8.5
|
|
# Sprinting variables. Similar to the variables above, just allowing for quicker movement
|
|
const MAX_SPRINT_SPEED = 34
|
|
const SPRINT_ACCEL = 18
|
|
# How fast we slow down, and the steepest angle we can climb.
|
|
const DEACCEL = 28
|
|
const MAX_SLOPE_ANGLE = 40
|
|
# How fast the bullets launch
|
|
const LEFT_MOUSE_FIRE_TIME = 0.15
|
|
const BULLET_SPEED = 100
|
|
|
|
var vel = Vector3()
|
|
# A vector for storing the direction the player intends to walk towards.
|
|
var dir = Vector3()
|
|
# A boolean to track whether or not we are sprinting
|
|
var is_sprinting = false
|
|
|
|
# You may need to adjust depending on the sensitivity of your mouse
|
|
var MOUSE_SENSITIVITY = 0.08
|
|
|
|
# A boolean for tracking whether the jump button is down
|
|
var jump_button_down = false
|
|
|
|
# The current lean value (our position on the lean track) and the path follow node
|
|
var lean_value = 0.5
|
|
|
|
# A variable for tracking if the right mouse button is down.
|
|
var right_mouse_down = false
|
|
# A variable for tracking if we can fire using the left mouse button
|
|
var left_mouse_timer = 0
|
|
|
|
# A boolean for tracking whether we can change animations or not
|
|
var anim_done = true
|
|
# The current animation name
|
|
var current_anim = "Starter"
|
|
|
|
# The simple bullet rigidbody
|
|
var simple_bullet = preload("res://fps/simple_bullet.tscn")
|
|
|
|
# We need the camera for getting directional vectors. We rotate ourselves on the Y-axis using
|
|
# the camera_holder to avoid rotating on more than one axis at a time.
|
|
@onready var camera_holder = $CameraHolder
|
|
@onready var camera = $CameraHolder/LeanPath/PathFollow3D/IK_LookAt_Chest/Camera3D
|
|
@onready var path_follow_node = $CameraHolder/LeanPath/PathFollow3D
|
|
# The animation player for aiming down the sights.
|
|
@onready var anim_player = $CameraHolder/AnimationPlayer
|
|
# The end of the pistol.
|
|
@onready var pistol_end = $CameraHolder/Weapon/Pistol/PistolEnd
|
|
|
|
|
|
func _ready():
|
|
anim_player.animation_finished.connect(animation_finished)
|
|
|
|
set_physics_process(true)
|
|
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
|
set_process_input(true)
|
|
|
|
|
|
func _physics_process(delta):
|
|
process_input(delta)
|
|
process_movement(delta)
|
|
|
|
|
|
func process_input(delta):
|
|
# Reset dir, so our previous movement does not effect us
|
|
dir = Vector3()
|
|
# Get the camera's global transform so we can use its directional vectors
|
|
var cam_xform = camera.get_global_transform()
|
|
|
|
# ----------------------------------
|
|
# Walking
|
|
if Input.is_key_pressed(KEY_UP) or Input.is_key_pressed(KEY_W):
|
|
dir += -cam_xform.basis[2]
|
|
if Input.is_key_pressed(KEY_DOWN) or Input.is_key_pressed(KEY_S):
|
|
dir += cam_xform.basis[2]
|
|
if Input.is_key_pressed(KEY_LEFT) or Input.is_key_pressed(KEY_A):
|
|
dir += -cam_xform.basis[0]
|
|
if Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_D):
|
|
dir += cam_xform.basis[0]
|
|
|
|
if Input.is_action_just_pressed(&"ui_cancel"):
|
|
if Input.get_mouse_mode() == Input.MOUSE_MODE_VISIBLE:
|
|
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
|
else:
|
|
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
|
|
|
if Input.is_mouse_button_pressed(2):
|
|
if not right_mouse_down:
|
|
right_mouse_down = true
|
|
|
|
if anim_done:
|
|
if current_anim != "Aiming":
|
|
anim_player.play("Aiming")
|
|
current_anim = "Aiming"
|
|
else:
|
|
anim_player.play("Idle")
|
|
current_anim = "Idle"
|
|
|
|
anim_done = false
|
|
else:
|
|
right_mouse_down = false
|
|
|
|
if Input.is_mouse_button_pressed(1):
|
|
if left_mouse_timer <= 0:
|
|
left_mouse_timer = LEFT_MOUSE_FIRE_TIME
|
|
|
|
# Create a bullet
|
|
var new_bullet = simple_bullet.instantiate()
|
|
get_tree().root.add_child(new_bullet)
|
|
new_bullet.global_transform = pistol_end.global_transform
|
|
new_bullet.linear_velocity = new_bullet.global_transform.basis.z * BULLET_SPEED
|
|
if left_mouse_timer > 0:
|
|
left_mouse_timer -= delta
|
|
# ----------------------------------
|
|
|
|
# ----------------------------------
|
|
# Sprinting
|
|
if Input.is_key_pressed(KEY_SHIFT):
|
|
is_sprinting = true
|
|
else:
|
|
is_sprinting = false
|
|
# ----------------------------------
|
|
|
|
# ----------------------------------
|
|
# Jumping
|
|
if Input.is_key_pressed(KEY_SPACE):
|
|
if not jump_button_down:
|
|
jump_button_down = true
|
|
if is_on_floor():
|
|
vel.y = JUMP_SPEED
|
|
else:
|
|
jump_button_down = false
|
|
# ----------------------------------
|
|
|
|
# ----------------------------------
|
|
# Leaning
|
|
if Input.is_key_pressed(KEY_Q):
|
|
lean_value += 1.2 * delta
|
|
elif Input.is_key_pressed(KEY_E):
|
|
lean_value -= 1.2 * delta
|
|
else:
|
|
if lean_value > 0.5:
|
|
lean_value -= 1 * delta
|
|
if lean_value < 0.5:
|
|
lean_value = 0.5
|
|
elif lean_value < 0.5:
|
|
lean_value += 1 * delta
|
|
if lean_value > 0.5:
|
|
lean_value = 0.5
|
|
|
|
lean_value = clamp(lean_value, 0, 1)
|
|
path_follow_node.h_offset = lean_value
|
|
if lean_value < 0.5:
|
|
var lerp_value = lean_value * 2
|
|
path_follow_node.rotation_degrees.z = (20 * (1 - lerp_value))
|
|
else:
|
|
var lerp_value = (lean_value - 0.5) * 2
|
|
path_follow_node.rotation_degrees.z = (-20 * lerp_value)
|
|
# ----------------------------------
|
|
|
|
|
|
func process_movement(delta):
|
|
var grav = norm_grav
|
|
|
|
dir.y = 0
|
|
dir = dir.normalized()
|
|
|
|
vel.y += delta * grav
|
|
|
|
var hvel = vel
|
|
hvel.y = 0
|
|
|
|
var target = dir
|
|
if is_sprinting:
|
|
target *= MAX_SPRINT_SPEED
|
|
else:
|
|
target *= MAX_SPEED
|
|
|
|
var accel
|
|
if dir.dot(hvel) > 0:
|
|
if not is_sprinting:
|
|
accel = ACCEL
|
|
else:
|
|
accel = SPRINT_ACCEL
|
|
else:
|
|
accel = DEACCEL
|
|
|
|
hvel = hvel.lerp(target, accel * delta)
|
|
|
|
vel.x = hvel.x
|
|
vel.z = hvel.z
|
|
|
|
# TODO: This information should be set to the CharacterBody properties instead of arguments.
|
|
velocity = vel
|
|
move_and_slide()
|
|
|
|
|
|
# Mouse based camera movement
|
|
func _input(event):
|
|
if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
|
|
rotate_y(deg_to_rad(event.screen_relative.x * MOUSE_SENSITIVITY * -1))
|
|
camera_holder.rotate_x(deg_to_rad(event.screen_relative.y * MOUSE_SENSITIVITY))
|
|
|
|
# We need to clamp the camera's rotation so we cannot rotate ourselves upside down
|
|
var camera_rot = camera_holder.rotation_degrees
|
|
if camera_rot.x < -40:
|
|
camera_rot.x = -40
|
|
elif camera_rot.x > 60:
|
|
camera_rot.x = 60
|
|
|
|
camera_holder.rotation_degrees = camera_rot
|
|
|
|
else:
|
|
pass
|
|
|
|
|
|
func animation_finished(_anim):
|
|
anim_done = true
|