summaryrefslogtreecommitdiff
path: root/player.gd
blob: d4c43dc87504f0b63ea27dc99eab8e9cb0b45402 (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
class_name Player
extends CharacterBody3D


var selection_block: MeshInstance3D
var selection_block_data: Block
var previous_looked_at_block_position: Vector3 = Vector3.ZERO

const SPEED = 5.0#10.0#20.0
const JUMP_VELOCITY = 5.0#10.0#20.0

var acc = 0


func _ready() -> void:
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	
	selection_block = MeshInstance3D.new()
	selection_block.visible = false
	selection_block.top_level = true
	selection_block.rotation = Vector3.ZERO
	selection_block.scale = Vector3(1.0001, 1.0001, 1.0001)
	add_child(selection_block)
	selection_block_data = Block.new()
	selection_block_data.type = Block.Type.SELECTION
	
	#set_physics_process(false)
	#await get_tree().create_timer(3.0).timeout
	#set_physics_process(true)


func _input(event: InputEvent) -> void:
	if event is InputEventMouse and event.is_pressed():
		Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	if event.is_action_pressed("mouse_exit"):
		Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	
	if Input.mouse_mode != Input.MOUSE_MODE_CAPTURED:
		return
	
	if event is InputEventMouseMotion:
		$CameraAnchor.rotate_y(deg_to_rad(clamp(-event.relative.x * 0.25, -45, 45)))
		$CameraAnchor.rotate_object_local(Vector3(1,0,0), deg_to_rad(-event.relative.y * 0.25))
	
	if event.is_action_pressed("right_click"):
		if selection_block.visible:
			var point = (
				$CameraAnchor/Camera/RayCast3D.get_collision_point() +
				$CameraAnchor/Camera/RayCast3D.get_collision_normal() * (Block.BLOCK_SIZE * 0.5)
			)
			
			var q := PhysicsShapeQueryParameters3D.new()
			q.shape = BoxShape3D.new()
			q.transform = Transform3D(Basis(Vector3.ZERO,Vector3.ZERO,Vector3.ZERO), point)
			var collision := get_world_3d().direct_space_state.intersect_shape(q)
			
			if collision.is_empty():
				(get_tree().current_scene as World).add_block(
					$CameraAnchor/Camera/RayCast3D.get_collision_point(),
					$CameraAnchor/Camera/RayCast3D.get_collision_normal(),
					$CanvasLayer/MarginContainer.active_type
				)
	
	if event.is_action_pressed("left_click"):
		if selection_block.visible:
			(get_tree().current_scene as World).remove_block(
				$CameraAnchor/Camera/RayCast3D.get_collision_point(),
				$CameraAnchor/Camera/RayCast3D.get_collision_normal()
			)


func _process(_delta: float) -> void:
	if $CameraAnchor/Camera/RayCast3D.is_colliding():
		var collider = $CameraAnchor/Camera/RayCast3D.get_collider()
		if collider is not StaticBody3D:
			return
		
		var point = $CameraAnchor/Camera/RayCast3D.get_collision_point()
		maybe_update_selection_block(point)
	else:
		selection_block.visible = false


func _physics_process(delta: float) -> void:
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta * 1.5

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# 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("ui_left", "ui_right", "ui_up", "ui_down")
	var direction := (
		(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
			.rotated(Vector3(1, 0, 0), $CameraAnchor.rotation.x)
			.rotated(Vector3(0, 1, 0), $CameraAnchor.rotation.y)
			.rotated(Vector3(0, 0, 1), $CameraAnchor.rotation.z)
	)
	if direction:
		velocity.x = direction.x * SPEED * (2.0 if Input.is_action_pressed("run") else 1.0) * (0.5 if not is_on_floor() else 1.0)
		velocity.z = direction.z * SPEED * (2.0 if Input.is_action_pressed("run") else 1.0) * (0.5 if not is_on_floor() else 1.0)
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	move_and_slide()


func maybe_update_selection_block(collision_point: Vector3) -> void:
	var chunk_idx := Chunk.global_to_chunk(
		collision_point,
		$CameraAnchor/Camera/RayCast3D.get_collision_normal()
	)
	var block_chunk_idx := Chunk.global_to_chunk_block(
		collision_point,
		$CameraAnchor/Camera/RayCast3D.get_collision_normal()
	)
	
	if Chunk.chunk_exists(chunk_idx):
		var chunk: Chunk = Global.chunks[chunk_idx]
		var block: Block = chunk.blocks[block_chunk_idx.x][block_chunk_idx.y][block_chunk_idx.z]
		
		selection_block.visible = true
		
		if previous_looked_at_block_position != block.position:
			update_selection_block(block.position)
			previous_looked_at_block_position = block.position


func update_selection_block(new_position: Vector3):
	var material := preload("res://new_shader_material_selection.tres")
	var st = SurfaceTool.new()
	st.begin(Mesh.PRIMITIVE_TRIANGLES)
	st.set_material(material)
	
	for face in Block.Face.values():
		selection_block_data.add_face(st, face)
	
	selection_block.global_position = new_position
	selection_block.mesh = st.commit()


func print_debug_block(message: String, block: Block) -> void:
	print(
		message.rpad(6), " => ",
		block, " ",
		Block.Type.keys()[block.type].rpad(5), " ",
		block.generated_faces
	)