Now About Social Code
summaryrefslogtreecommitdiff
path: root/scripts/player.gd
blob: 69ba9104100ec4b4baac0059d037e7a87a175d46 (plain)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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()

var inital_camera_offset: Vector3 = Vector3()
var camera_rotation: float = 0

func got_body(body: Node3D):
	if current_node == null:
		print("Got body ", body)
		current_node = body

func leave_body(body: Node3D):
	if current_node == body:
		current_node = null
		
func pickup():
	if current_node.collision_layer & 0b1000:
		num_seeds += 1
		var node = current_node
		node.get_parent().remove_child(node)
		node.queue_free()
			
	elif 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 get_camera_fwd() -> Vector3:
	var fwd: Vector3 = -Vector3(sin(camera_rotation), 0, cos(camera_rotation))
	return fwd
	
func get_camera_right() -> Vector3:
	var right: Vector3 = Vector3(cos(camera_rotation), 0, -sin(camera_rotation))
	return right
		
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 = get_camera_fwd()
	var right = get_camera_right()
	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)
	
	$Picker.connect("body_entered", got_body)
	$Picker.connect("body_exited", leave_body)
	
	inital_camera_offset = $Camera3D.global_position - global_position
	
func _process(delta: float):
	stam_bar.value = stamina
	seed_text.text = str(num_seeds)
	
	turn_camera(delta)
	
func turn_camera(delta: float):
	var turn_amt = Input.get_axis("turn_right", "turn_left")
	camera_rotation += turn_amt * delta

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 = get_camera_fwd()
	var right = get_camera_right()
	
	var valid_climb = false
	if is_on_wall():
		for col in get_slide_collision_count():
			var col_obj = get_slide_collision(col)
			#print("Collider layer is ", col_obj.get_collider().collision_layer, " ", col_obj.get_collider())
			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
	elif climbing:
		climbing = false
	
	var climb_direction_fwd = Vector3()
	var climb_direction_right = Vector3()
	if climbing:
		climb_direction_fwd = (Vector3.UP - Vector3.UP.project(last_wall_direction)).normalized()
		
		# TODO
		# This should not be relative to the camera, climbing should be fixed, I think I might need
		# to take a cross product here to do that with the wall normal and the fwd/up direction on the wall
		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
	
	# Make sure player is looking in the forward direction
	# TODO player should only start looking at the fwd direction when they start moving
	look_at(global_position + fwd)
	
	# 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: Vector3 = (input_dir.y * climb_direction_fwd + input_dir.x * climb_direction_right).normalized()
	if climbing:
		velocity = climb_direction * speed
		
		# TODO there should be some way to force the player to be locked to the wall without 
		# just pushing into the wall slightly.
		velocity += -speed * last_wall_direction
		if input_dir.length_squared() > 0:
			stam_consumption += RUN_CONSUMPTION
		
		# Force player to look toward wall
		look_at(global_position - last_wall_direction)
		
		# Set camera rotation so it continues to face the wall
		# TODO player should still be able to move the camera, this should probably just nudge the camera to this
		# position while climbing and not controling the camera
		camera_rotation = Vector2(last_wall_direction.x, last_wall_direction.z).angle_to(Vector2(inital_camera_offset.x, inital_camera_offset.z))
	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()
	
	# Position camera
	$Camera3D.global_position = global_position + inital_camera_offset.rotated(Vector3.UP, camera_rotation)
	$Camera3D.look_at(global_position)
	
	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)