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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
extends CharacterBody3D
const SPEED = 5.0
const RUN_SPEED = 1.5 * SPEED
const JUMP_VELOCITY = 4.5
const THROW_FORCE = 10.0
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var current_node: Node3D = null
var holding: Node3D = null
var climbing: bool = false
var last_wall_direction: Vector3 = Vector3()
func got_body(body: Node3D):
if current_node == null:
current_node = body
func leave_body(body: Node3D):
if current_node == body:
current_node = null
func pickup():
if holding == null:
holding = current_node
current_node.get_parent().remove_child(current_node)
holding.position = Vector3.ZERO
holding.freeze = true
$Holder.add_child(holding)
func throw():
var g_pos = holding.global_position
holding.get_parent().remove_child(holding)
get_parent().add_child(holding)
holding.global_position = g_pos
var fwd = $ThirdPersonCamera.get_front_direction()
var right = Vector3.UP
var dir = (fwd + right).normalized()
holding.freeze = false
holding.apply_impulse(THROW_FORCE*dir)
holding = null
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
$ThirdPersonCamera.mouse_follow = true
$Picker.connect("body_entered", got_body)
$Picker.connect("body_exited", leave_body)
func _physics_process(delta):
var speed = SPEED
if Input.is_action_pressed("run"):
speed = RUN_SPEED
if Input.is_action_just_pressed("pickup"):
if holding == null and current_node != null:
pickup()
elif holding != null:
throw()
# Add the gravity.
if not is_on_floor() and not climbing:
velocity.y -= gravity * delta
var fwd = $ThirdPersonCamera.get_front_direction()
var right = $ThirdPersonCamera.get_right_direction()
var climb_direction_fwd = Vector3()
var climb_direction_right = Vector3()
if is_on_wall():
last_wall_direction = get_wall_normal()
climbing = true
print("Climbing now")
elif climbing:
climbing = false
print("Not climbing")
if climbing:
climb_direction_fwd = (Vector3.UP - Vector3.UP.project(last_wall_direction)).normalized()
climb_direction_right = (right - right.project(last_wall_direction)).normalized()
# Handle Jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
look_at(position + fwd, Vector3.UP)
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var input_dir = Input.get_vector("left", "right", "backward", "forward")
var direction = (input_dir.y * fwd + input_dir.x * right).normalized()
var climb_direction = (input_dir.y * climb_direction_fwd + input_dir.x * climb_direction_right).normalized()
if climbing:
print("Climb direction is ", climb_direction_fwd, " ", climb_direction_right, " ", get_wall_normal())
velocity = climb_direction * speed
velocity += -speed * last_wall_direction
print("Velocity is ", velocity)
elif direction:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
velocity.z = move_toward(velocity.z, 0, speed)
move_and_slide()
|