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
)
|