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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
extends CharacterBody3D
const SPEED = 5.0
const RUN_SPEED = 1.5 * SPEED
const JUMP_VELOCITY = 4.5
const THROW_FORCE = 10.0
const RUN_CONSUMPTION = 20.0
const STAM_REGEN = 10.0
#@export_node_path("ProgressBar") var stam_bar_path = null
@export var stam_bar: ProgressBar = null;
@export var seed_text: RichTextLabel = null;
var stamina: float = 100
var num_seeds: int = 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():
assert(stam_bar != null, "Stamina bar is null")
assert(seed_text != null, "Seed text is null")
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 _process(_delta):
stam_bar.value = stamina
seed_text.text = str(num_seeds)
func _physics_process(delta):
var speed = SPEED
var stam_consumption = 0
if Input.is_action_pressed("run") and stamina > 0:
speed = RUN_SPEED
stam_consumption += RUN_CONSUMPTION
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()
var valid_climb = false
if is_on_wall():
for col in get_slide_collision_count():
var col_obj = get_slide_collision(col)
print(col_obj.get_collider().collision_layer)
if col_obj.get_collider().collision_layer & 0b100:
valid_climb = true
if valid_climb and stamina > 0:
last_wall_direction = get_wall_normal()
climbing = true
stam_consumption += RUN_CONSUMPTION
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()
if stam_consumption == 0 and not Input.is_action_pressed("run") and is_on_floor():
stam_consumption = -STAM_REGEN
stamina = clamp(stamina - stam_consumption * delta, 0, 100)
|