FPS Controller
This commit is contained in:
13
demo/assets/scripts/player/components/interaction_raycast.gd
Normal file
13
demo/assets/scripts/player/components/interaction_raycast.gd
Normal file
@@ -0,0 +1,13 @@
|
||||
extends RayCast3D
|
||||
|
||||
var current_object
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if is_colliding():
|
||||
var object = get_collider()
|
||||
if object == current_object:
|
||||
return
|
||||
else:
|
||||
current_object = object
|
||||
else:
|
||||
current_object = null
|
||||
@@ -0,0 +1 @@
|
||||
uid://bqeyf8hqbc7xy
|
||||
26
demo/assets/scripts/player/components/mouse_capture.gd
Normal file
26
demo/assets/scripts/player/components/mouse_capture.gd
Normal file
@@ -0,0 +1,26 @@
|
||||
class_name MouseCaptureComponent extends Node
|
||||
|
||||
@export var debug : bool = false
|
||||
@export_category("Mouse Capture Settings")
|
||||
@export var current_mouse_mode : Input.MouseMode = Input.MOUSE_MODE_CAPTURED
|
||||
@export var mouse_sensitivity : float = 0.005
|
||||
|
||||
var _capture_mouse : bool
|
||||
var _mouse_input : Vector2
|
||||
|
||||
|
||||
## Captures the relative mouse movement from the center of the screen
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
_capture_mouse = event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED
|
||||
if _capture_mouse:
|
||||
_mouse_input.x += -event.screen_relative.x * mouse_sensitivity
|
||||
_mouse_input.y += -event.screen_relative.y * mouse_sensitivity
|
||||
if debug:
|
||||
print(_mouse_input)
|
||||
|
||||
func _ready() -> void:
|
||||
Input.mouse_mode = current_mouse_mode
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
_mouse_input = Vector2.ZERO
|
||||
@@ -0,0 +1 @@
|
||||
uid://d0xgg3pig4b6i
|
||||
11
demo/assets/scripts/player/components/state_machine.gd
Normal file
11
demo/assets/scripts/player/components/state_machine.gd
Normal file
@@ -0,0 +1,11 @@
|
||||
class_name PlayerStateMachine extends Node
|
||||
|
||||
@export var debug : bool = false
|
||||
@export_category("References")
|
||||
@export var player_controller : PlayerController
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if player_controller:
|
||||
player_controller.state_chart.set_expression_property("Player Velocity", player_controller.velocity)
|
||||
player_controller.state_chart.set_expression_property("Player Hitting Head", player_controller.crouch_check.is_colliding())
|
||||
player_controller.state_chart.set_expression_property("Looking At: ", player_controller.interaction_raycast.current_object)
|
||||
@@ -0,0 +1 @@
|
||||
uid://cqrpha4131qgx
|
||||
83
demo/assets/scripts/player/components/step_climber.gd
Normal file
83
demo/assets/scripts/player/components/step_climber.gd
Normal file
@@ -0,0 +1,83 @@
|
||||
class_name StepHandlerComponet extends Node
|
||||
|
||||
@export_category("References")
|
||||
@export var player: PlayerController
|
||||
@export_category("Step Settings")
|
||||
@export var surface_threshold: float = 0.3
|
||||
@export var step_height: float = 0.3
|
||||
|
||||
const FEET_ADJUSTED_HEIGHT = 0.05
|
||||
const MIN_MOVEMENT_LENGTH: float = 0.1
|
||||
const MIN_DOT_VALUE: float = 0.5
|
||||
const MIN_STEP_HEIGHT: float = 0.1
|
||||
|
||||
func handle_step_climbing():
|
||||
for i in player.get_slide_collision_count():
|
||||
var collision = player.get_slide_collision(i)
|
||||
if _is_surface_verical(collision):
|
||||
var measured_height = _measure_step_height(collision)
|
||||
if measured_height > MIN_STEP_HEIGHT and measured_height <= step_height and _is_valid_step_direction(collision):
|
||||
player.global_position.y += measured_height
|
||||
player.velocity = player.previous_velocity
|
||||
player.camera.smooth_step(measured_height)
|
||||
|
||||
func _is_valid_step_direction(collision: KinematicCollision3D):
|
||||
var collision_normal = collision.get_normal()
|
||||
var input_dir = player.get_input_direction()
|
||||
var movement_direction = player.transform.basis * Vector3(input_dir.x, 0, input_dir.y)
|
||||
if movement_direction.length() > MIN_MOVEMENT_LENGTH:
|
||||
movement_direction = movement_direction.normalized()
|
||||
var dot_product = movement_direction.dot(-collision_normal)
|
||||
return dot_product > MIN_DOT_VALUE
|
||||
return false
|
||||
|
||||
func _measure_step_height(collision: KinematicCollision3D) -> float:
|
||||
var space_state = player.get_world_3d().direct_space_state
|
||||
var collision_point = collision.get_position()
|
||||
|
||||
var player_feet = _get_player_feet_position()
|
||||
var player_head_y = player.global_position.y + (player.standing_collision.shape.height / 2)
|
||||
|
||||
var ray_start = Vector3(collision_point.x, player_head_y, collision_point.z)
|
||||
var ray_end = Vector3(collision_point.x, player_feet.y, collision_point.z)
|
||||
|
||||
var query = PhysicsRayQueryParameters3D.create(ray_start, ray_end)
|
||||
query.collision_mask = player.collision_mask
|
||||
query.exclude = [player.get_rid()]
|
||||
|
||||
var result = space_state.intersect_ray(query)
|
||||
if result:
|
||||
return result.position.y - player_feet.y
|
||||
|
||||
return 0.0
|
||||
|
||||
func _is_surface_verical(collision: KinematicCollision3D) -> bool:
|
||||
var normal = collision.get_normal()
|
||||
if abs(normal.y) <= surface_threshold:
|
||||
return true
|
||||
|
||||
return _check_collison_surface(collision)
|
||||
|
||||
# additional work to validate
|
||||
func _check_collison_surface(collision: KinematicCollision3D) -> bool:
|
||||
var space_state = player.get_world_3d().direct_space_state
|
||||
var collision_point = collision.get_position()
|
||||
|
||||
var player_feet: Vector3 = _get_player_feet_position()
|
||||
collision_point.y = player_feet.y
|
||||
|
||||
var query = PhysicsRayQueryParameters3D.create(player_feet, collision_point)
|
||||
query.collision_mask = player.collision_mask
|
||||
query.exclude = [player.get_rid()]
|
||||
|
||||
var result = space_state.intersect_ray(query)
|
||||
if result and abs(result.normal.y) <= surface_threshold:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func _get_player_feet_position() -> Vector3:
|
||||
var feet_pos = player.global_position
|
||||
feet_pos.y -= player.standing_collision.shape.height / 2
|
||||
feet_pos.y += FEET_ADJUSTED_HEIGHT
|
||||
return feet_pos
|
||||
@@ -0,0 +1 @@
|
||||
uid://b1us8up0jvwjb
|
||||
Reference in New Issue
Block a user