summaryrefslogtreecommitdiffstats
path: root/character/fps_controller/fps_controller.gd
blob: 8d5af1278210b57642f7eacda5fdd8415078e49f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
extends KinematicBody

onready var camera = $Camera
onready var ray = $Camera/RayCast
onready var ladder_area = $ladder_detector

export var walk_speed : int = 10
export var accel : float = 0.2
export var gravity : int = -1
export var term_velocity : int = -35
export var jump_strength : int = 20
export var inertia : int = 5

var velocity : Vector3
var is_climbing : bool = false

func _ready():
    Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _process(_delta):
    get_input()

func _physics_process(_delta):
    handle_movement()
    handle_jumping()
    handle_collision()

func get_input():
    var dir : Vector3 = Vector3.ZERO
    #Get base movement input
    if Input.is_action_pressed("forward"):
        dir += -global_transform.basis.z
        if is_climbing:
            dir += global_transform.basis.y
    if Input.is_action_pressed("backward"):
        dir += global_transform.basis.z
        if is_climbing:
            dir += -global_transform.basis.y
    if Input.is_action_pressed("left"):
        dir += -global_transform.basis.x
    if Input.is_action_pressed("right"):
        dir += global_transform.basis.x
    dir = dir.normalized()
    #Pull X and Z values from directional input. Velocity.y will be handled in physics loop unless climbing.
    
    if is_climbing:
        velocity.y = lerp(velocity.y, dir.y * walk_speed, accel)
    velocity.x = lerp(velocity.x, dir.x * walk_speed, accel)
    velocity.z = lerp(velocity.z, dir.z * walk_speed, accel)

func handle_movement():
    #Apply gravity
    if !is_climbing:
        velocity.y += gravity
        if velocity.y < term_velocity:
            velocity.y = term_velocity
    velocity = move_and_slide_with_snap(velocity, Vector3.DOWN if velocity.y <= 0.0 else Vector3.ZERO, Vector3.UP, true, 4, PI/4, false)

func _input(event):
    #Handle mouse movement for camera
    if event is InputEventMouseMotion:
        self.rotate_y(-event.relative.x * Settings.mouse_sens)
        camera.rotate_x(-event.relative.y * Settings.mouse_sens)
        camera.rotation.x = clamp(camera.rotation.x, -1.2, 1.2)

func handle_jumping():
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_strength
func handle_collision():
    for index in get_slide_count():
        var collision = get_slide_collision(index)
        var collider = collision.collider
        if (collider.get_class() == "RigidBody"):
            var col_force_vec = -collision.normal * inertia # rotate the force along collision normal
            # collision pos
            # > RigidBody.add_force(force, pos) > The position uses the rotation of the global coordinate system, but is centered at the object's origin.
            # > KinematicCollision.position() > The point of collision, in global coordinates.
            # So to add force at collision position, substract colliders pos from collision.position
            var col_pos = collision.position - collider.transform.origin
            collider.add_force(col_force_vec, col_pos)


func _on_ladder_detector_body_entered(body):
    if body.is_in_group("ladder"):
        is_climbing = true


func _on_ladder_detector_body_exited(body):
    if body.is_in_group("ladder"):
        is_climbing = false