Player camera controller

This commit is contained in:
Rob Kelly 2025-09-29 12:38:13 -06:00
parent d6d3afa701
commit ddb55e7a7a
7 changed files with 105 additions and 2 deletions

View File

@ -51,3 +51,16 @@ folder_colors={
"res://src/": "green",
"res://src/world/": "teal"
}
[game]
config/input/mouse_sensitivity_x=0.3
config/input/mouse_sensitivity_y=0.3
config/input/camera_acceleration=40.0
config/input/invert_pitch=false
[layer_names]
3d_render/layer_1="Global Noise Layer"
3d_physics/layer_1="World Geometry"
3d_physics/layer_2="Player"

View File

@ -0,0 +1,21 @@
class_name CameraController extends Node3D
## Simple first-person camera motion controller
const PITCH_LIMIT := deg_to_rad(85.0)
@onready var _target := Vector2(rotation.x, rotation.y)
## Rotate the camera by the given motion vector.
##
## The input motion vector is the change in pitch and yaw in radians.
func camera_motion(motion: Vector2) -> void:
_target.y -= motion.x
_target.x = clampf(_target.x - motion.y, -PITCH_LIMIT, PITCH_LIMIT)
func _physics_process(delta: float) -> void:
var accel: float = ProjectSettings.get_setting("game/config/input/camera_acceleration")
var weight := 1.0 - exp(-accel * delta)
rotation.y = lerp_angle(rotation.y, _target.y, weight)
rotation.x = lerp_angle(rotation.x, _target.x, weight)

View File

@ -0,0 +1 @@
uid://f3kssctvn2bo

View File

@ -0,0 +1,28 @@
class_name MouselookController extends Node
## Camera controller component using the mouse to look around.
@export var look_enabled := true
@onready var camera_controller: CameraController = get_parent()
func _send_mouse_motion(motion: Vector2) -> void:
# Map mouse motion & send to controller
var x_sensitivity: float = ProjectSettings.get_setting("game/config/input/mouse_sensitivity_x")
var y_sensitivity: float = ProjectSettings.get_setting("game/config/input/mouse_sensitivity_y")
var invert_pitch: bool = ProjectSettings.get_setting("game/config/input/invert_pitch")
camera_controller.camera_motion(
Vector2(
deg_to_rad(motion.x * x_sensitivity),
deg_to_rad(motion.y * y_sensitivity) * (-1 if invert_pitch else 1)
)
)
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED and look_enabled:
_send_mouse_motion((event as InputEventMouseMotion).relative)
elif event is InputEventMouseButton and look_enabled:
# Capture mouse when clicked
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

View File

@ -0,0 +1 @@
uid://032jyhgkb2rv

View File

@ -1,13 +1,42 @@
[gd_scene load_steps=3 format=3 uid="uid://dtbulshrxetes"]
[gd_scene load_steps=8 format=3 uid="uid://dtbulshrxetes"]
[ext_resource type="Script" uid="uid://f3kssctvn2bo" path="res://src/player/camera_controller.gd" id="1_mf2ua"]
[ext_resource type="Script" uid="uid://csjccrhj5wnx7" path="res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd" id="1_rxibo"]
[ext_resource type="Script" uid="uid://8umksf8e80fw" path="res://addons/phantom_camera/scripts/resources/tween_resource.gd" id="2_mf2ua"]
[ext_resource type="Script" uid="uid://032jyhgkb2rv" path="res://src/player/mouselook_controller.gd" id="4_244u8"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_qnmj6"]
[sub_resource type="CapsuleMesh" id="CapsuleMesh_4anbu"]
[sub_resource type="Resource" id="Resource_244u8"]
script = ExtResource("2_mf2ua")
duration = 0.4
transition = 7
ease = 0
[node name="Player" type="CharacterBody3D"]
collision_layer = 3
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("CapsuleShape3D_qnmj6")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("CapsuleMesh_4anbu")
[node name="CameraOffset" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
[node name="CameraController" type="Node3D" parent="CameraOffset"]
script = ExtResource("1_mf2ua")
[node name="PhantomCamera3D" type="Node3D" parent="CameraOffset/CameraController"]
script = ExtResource("1_rxibo")
priority = 1
tween_resource = SubResource("Resource_244u8")
noise_emitter_layer = 1
metadata/_custom_type_script = "uid://csjccrhj5wnx7"
[node name="MouselookController" type="Node" parent="CameraOffset/CameraController"]
script = ExtResource("4_244u8")
metadata/_custom_type_script = "uid://032jyhgkb2rv"

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=5 format=3 uid="uid://daxngklaqlyba"]
[gd_scene load_steps=6 format=3 uid="uid://daxngklaqlyba"]
[ext_resource type="PackedScene" uid="uid://dtbulshrxetes" path="res://src/player/player.tscn" id="1_1k4gi"]
[ext_resource type="Script" uid="uid://bd046eokvcnu2" path="res://addons/phantom_camera/scripts/phantom_camera_host/phantom_camera_host.gd" id="2_6fy3g"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_kueii"]
albedo_color = Color(0.16, 0.16, 0.16, 1)
@ -23,3 +24,12 @@ mesh = SubResource("PlaneMesh_1k4gi")
[node name="CollisionShape3D" type="CollisionShape3D" parent="WorldFloor/StaticBody3D"]
shape = SubResource("WorldBoundaryShape3D_1k4gi")
[node name="Camera3D" type="Camera3D" parent="."]
physics_interpolation_mode = 1
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.5, 0)
[node name="PhantomCameraHost" type="Node" parent="Camera3D"]
process_priority = 300
process_physics_priority = 300
script = ExtResource("2_6fy3g")