summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Spritesheet_array.pngbin6886 -> 6906 bytes
-rw-r--r--Spritesheet_array.png~bin6613 -> 6913 bytes
-rw-r--r--block.gd118
-rw-r--r--block.gd.uid1
-rw-r--r--camera.gd.uid1
-rw-r--r--chunk.gd353
-rw-r--r--chunk.gd.uid1
-rw-r--r--chunk.tscn15
-rw-r--r--free-look-camera.gd11
-rw-r--r--free-look-camera.gd.uid1
-rw-r--r--global.gd10
-rw-r--r--global.gd.uid1
-rw-r--r--inventory_bar.gd43
-rw-r--r--inventory_bar.gd.uid1
-rw-r--r--main.gd367
-rw-r--r--main.gd.uid1
-rw-r--r--main.tscn116
-rw-r--r--new_shader.gdshader2
-rw-r--r--new_shader.gdshader.uid1
-rw-r--r--new_shader_material.tres4
-rw-r--r--new_shader_material_selection.tres10
-rw-r--r--new_shader_selection.gdshader23
-rw-r--r--new_shader_selection.gdshader.uid1
-rw-r--r--player.gd133
-rw-r--r--player.gd.uid1
-rw-r--r--project.godot75
26 files changed, 913 insertions, 377 deletions
diff --git a/Spritesheet_array.png b/Spritesheet_array.png
index 82159f8..6e3e519 100644
--- a/Spritesheet_array.png
+++ b/Spritesheet_array.png
Binary files differ
diff --git a/Spritesheet_array.png~ b/Spritesheet_array.png~
index 25a41fb..e6f3299 100644
--- a/Spritesheet_array.png~
+++ b/Spritesheet_array.png~
Binary files differ
diff --git a/block.gd b/block.gd
index bfa9928..5896266 100644
--- a/block.gd
+++ b/block.gd
@@ -1,11 +1,7 @@
class_name Block
-extends Resource
-const FACE_CORNERS = [
- Vector2(0, 0), Vector2(1, 0),
- Vector2(0, 1), Vector2(1, 1),
-]
+const BLOCK_SIZE := Vector3(1.0, 1.0, 1.0)
enum Face {
FRONT,
@@ -16,7 +12,7 @@ enum Face {
BOTTOM,
}
-const FACES = [
+var FACES = [
[ # FRONT
[Vector3(-1.0, 1.0, 1.0), Vector3(1.0, -1.0, 1.0), Vector3(-1.0, -1.0, 1.0)],
[Vector3(-1.0, 1.0, 1.0), Vector3(1.0, 1.0, 1.0), Vector3(1.0, -1.0, 1.0)],
@@ -43,7 +39,7 @@ const FACES = [
],
]
-const FACE_UVS = [
+var FACE_UVS = [
[ # FRONT
[Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)],
[Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)],
@@ -70,7 +66,7 @@ const FACE_UVS = [
],
]
-const FACE_NORMALS = [
+var FACE_NORMALS = [
Vector3(0, 0, 1), # FRONT
Vector3(0, 0, -1), # BACK
Vector3(-1, 0, 0), # LEFT
@@ -85,9 +81,18 @@ enum Type {
DIRT,
LEAVES,
STONE,
+ ICE,
+ WOOD,
+ SAND,
+ PLANKS,
+ YELLOW_STONE,
+ BLUE_STONE,
+ RED_STONE,
+ BLACK_STONE,
+ SELECTION,
}
-const BLOCK_TYPES = {
+var BLOCK_TYPES = {
Type.GRASS: {
"uv2s": [
Vector2(0, 0), # FRONT
@@ -128,9 +133,100 @@ const BLOCK_TYPES = {
Vector2(2, 0), # BOTTOM
],
},
+ Type.ICE: {
+ "uv2s": [
+ Vector2(2, 1), # FRONT
+ Vector2(2, 1), # BACK
+ Vector2(2, 1), # LEFT
+ Vector2(2, 1), # RIGHT
+ Vector2(2, 1), # TOP
+ Vector2(2, 1), # BOTTOM
+ ],
+ },
+ Type.WOOD: {
+ "uv2s": [
+ Vector2(5, 0), # FRONT
+ Vector2(5, 0), # BACK
+ Vector2(5, 0), # LEFT
+ Vector2(5, 0), # RIGHT
+ Vector2(5, 0), # TOP
+ Vector2(5, 0), # BOTTOM
+ ],
+ },
+ Type.SAND: {
+ "uv2s": [
+ Vector2(4, 0), # FRONT
+ Vector2(4, 0), # BACK
+ Vector2(4, 0), # LEFT
+ Vector2(4, 0), # RIGHT
+ Vector2(4, 0), # TOP
+ Vector2(4, 0), # BOTTOM
+ ],
+ },
+ Type.PLANKS: {
+ "uv2s": [
+ Vector2(0, 2), # FRONT
+ Vector2(0, 2), # BACK
+ Vector2(0, 2), # LEFT
+ Vector2(0, 2), # RIGHT
+ Vector2(0, 2), # TOP
+ Vector2(0, 2), # BOTTOM
+ ],
+ },
+ Type.YELLOW_STONE: {
+ "uv2s": [
+ Vector2(3, 1), # FRONT
+ Vector2(3, 1), # BACK
+ Vector2(3, 1), # LEFT
+ Vector2(3, 1), # RIGHT
+ Vector2(3, 1), # TOP
+ Vector2(3, 1), # BOTTOM
+ ],
+ },
+ Type.BLUE_STONE: {
+ "uv2s": [
+ Vector2(4, 1), # FRONT
+ Vector2(4, 1), # BACK
+ Vector2(4, 1), # LEFT
+ Vector2(4, 1), # RIGHT
+ Vector2(4, 1), # TOP
+ Vector2(4, 1), # BOTTOM
+ ],
+ },
+ Type.RED_STONE: {
+ "uv2s": [
+ Vector2(5, 1), # FRONT
+ Vector2(5, 1), # BACK
+ Vector2(5, 1), # LEFT
+ Vector2(5, 1), # RIGHT
+ Vector2(5, 1), # TOP
+ Vector2(5, 1), # BOTTOM
+ ],
+ },
+ Type.BLACK_STONE: {
+ "uv2s": [
+ Vector2(1, 2), # FRONT
+ Vector2(1, 2), # BACK
+ Vector2(1, 2), # LEFT
+ Vector2(1, 2), # RIGHT
+ Vector2(1, 2), # TOP
+ Vector2(1, 2), # BOTTOM
+ ],
+ },
+ Type.SELECTION: {
+ "uv2s": [
+ Vector2(3, 2), # FRONT
+ Vector2(3, 2), # BACK
+ Vector2(3, 2), # LEFT
+ Vector2(3, 2), # RIGHT
+ Vector2(3, 2), # TOP
+ Vector2(3, 2), # BOTTOM
+ ],
+ },
}
-var position: Vector3
+var position: Vector3i
+var global_position: Vector3i
var type: Type
@@ -146,7 +242,7 @@ func add_face(surface_tool: SurfaceTool, face: Face):
for idx in FACES[face].size():
var triangle = FACES[face][idx]
var triangle_positions = triangle.map(func(item):
- return item + position
+ return (item * (BLOCK_SIZE * 0.5)) + Vector3(global_position) + (BLOCK_SIZE * 0.5)
)
var uvs = FACE_UVS[face][idx]
diff --git a/block.gd.uid b/block.gd.uid
new file mode 100644
index 0000000..8ddae71
--- /dev/null
+++ b/block.gd.uid
@@ -0,0 +1 @@
+uid://nk24rejftjmm
diff --git a/camera.gd.uid b/camera.gd.uid
new file mode 100644
index 0000000..e8ffa25
--- /dev/null
+++ b/camera.gd.uid
@@ -0,0 +1 @@
+uid://cja33lro5ww7n
diff --git a/chunk.gd b/chunk.gd
index 8dcd416..2003c4e 100644
--- a/chunk.gd
+++ b/chunk.gd
@@ -1,90 +1,301 @@
class_name Chunk
-extends Node
+extends Node3D
-var chunk_size := Vector3(16, 16, 16)
+var grid_position := Vector3i.ZERO
+var mesh: ArrayMesh = ArrayMesh.new()
@export var noise: FastNoiseLite
+@export var blocks: Array = []
-var blocks: Array[Block] = []
-
-func generate_chunk(row, column, depth):
- #var material := StandardMaterial3D.new()
- #material.albedo_texture = preload("res://new_atlas_texture.tres")
- #material.vertex_color_use_as_albedo = true
- var material := preload("res://new_shader_material.tres")
- var st = SurfaceTool.new()
- st.begin(Mesh.PRIMITIVE_TRIANGLES)
- st.set_material(material)
+func generate_block_data(row: int, column: int, depth: int, empty: bool = false):
+ grid_position = Vector3i(row, column, depth)
- var blocks = []
+ blocks = []
+ blocks.resize(Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * Global.CHUNK_SIZE.z)
- for x in chunk_size.x:
- #blocks[x] = []
- blocks.append([])
- for y in chunk_size.y:
- #blocks[x][y] = []
- blocks[x].append([])
- for z in chunk_size.z:
- var block_position = Vector3(
- row*chunk_size.x + x,
- column*chunk_size.y + y,
- depth*chunk_size.z + z
- #x,
- #y,
- #z
- ) * 2
- var value = noise.get_noise_3d(block_position.x, block_position.y, block_position.z) * 100
+ for x in Global.CHUNK_SIZE.x:
+ for z in Global.CHUNK_SIZE.z:
+ var block_position := Vector3i(x, 0, z)
+ var block_global_position := Vector3i(
+ grid_position.x * Global.CHUNK_SIZE.x + block_position.x,
+ 0,
+ grid_position.z * Global.CHUNK_SIZE.z + block_position.z
+ )
+ var height := Global.CHUNK_SIZE.y
+
+ if grid_position.y >= Global.GROUND_LEVEL:
+ var noise_2d := noise.get_noise_2d(
+ block_global_position.x,
+ block_global_position.z
+ ) * 100
+ height = round(clamp(abs(noise_2d), 0, Global.CHUNK_SIZE.y))
+
+ for y in Global.CHUNK_SIZE.y:
+ block_position.y = y
+ block_global_position. y = grid_position.y * Global.CHUNK_SIZE.y + block_position.y
+
+ var value = noise.get_noise_3d(
+ block_global_position.x,
+ block_global_position.y,
+ block_global_position.z
+ ) * 100
- var type = Block.Type.AIR
- if value > -15:
- type = Block.Type.GRASS
- elif value > -20:
- type = Block.Type.STONE
+ var type := Block.Type.AIR
+ if height < y:
+ type = Block.Type.AIR
+ else:
+ if value > -15:
+ type = Block.Type.GRASS
+ elif value > -20:
+ type = Block.Type.STONE
+ #if value > 4:
+ #type = Block.Type.GRASS
+ #if value < -4:
+ #type = Block.Type.STONE
+ ##if value < -16:
+ ##type = Block.Type.DIRT
+ #if value < -17 and value > -20:
+ #type = Block.Type.SAND
+ #if abs(value) > 21 and abs(value) < 21.25:
+ #type = [Block.Type.STONE, Block.Type.YELLOW_STONE, Block.Type.BLUE_STONE, Block.Type.RED_STONE, Block.Type.BLACK_STONE].pick_random()
+ ##print(value)
var block = Block.new()
block.position = block_position
+ block.global_position = block_global_position
block.type = type
- blocks[x][y].append(block)
-
- for x in blocks.size():
- for y in blocks[x].size():
- for z in blocks[x][y].size():
- var block = blocks[x][y][z]
- var block_position = block.position
+ if empty or Global.MAX_HEIGHT < block.global_position.y:
+ block.type = Block.Type.AIR
- if not block.type == Block.Type.AIR:
- if block.type == Block.Type.GRASS and blocks[x].size() > y + 1 and not blocks[x][y + 1][z].type == Block.Type.AIR:
- block.type = Block.Type.DIRT
-
- var rng = RandomNumberGenerator.new()
- rng.seed = randi()
- st.set_color(Color(rng.randf(), rng.randf(), rng.randf()))
-
- st.set_uv(Vector2(0, 0))
-
- if (blocks[x][y].size() > z+1 and blocks[x][y][z + 1].type == Block.Type.AIR) or blocks[x][y].size() == z+1:
- block.add_face(st, Block.Face.FRONT, block)
-
- if (blocks.size() > x+1 and blocks[x + 1][y][z].type == Block.Type.AIR) or blocks.size() == x+1:
- block.add_face(st, Block.Face.RIGHT)
-
- if blocks[x][y].size() > z-1 and (blocks[x][y][z - 1].type == Block.Type.AIR or z == 0):
- block.add_face(st, Block.Face.BACK)
-
- if blocks.size() > x-1 and (blocks[x - 1][y][z].type == Block.Type.AIR or x == 0):
- block.add_face(st, Block.Face.LEFT)
-
- if (blocks[x].size() > y+1 and blocks[x][y + 1][z].type == Block.Type.AIR) or blocks[x].size() == y+1:
- block.add_face(st, Block.Face.TOP)
-
- if blocks[x].size() > y-1 and (blocks[x][y - 1][z].type == Block.Type.AIR or y == 0):
- block.add_face(st, Block.Face.BOTTOM)
+ var index := x + Global.CHUNK_SIZE.x * y + Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * z
+ blocks[index] = block
+
+
+func generate_mesh():
+ var material := preload("res://new_shader_material.tres")
+ var st = SurfaceTool.new()
+ st.begin(Mesh.PRIMITIVE_TRIANGLES)
+ st.set_material(material)
+
+ for index in blocks.size():
+ var block: Block = blocks[index]
+ if block.type == Block.Type.AIR:
+ continue
+
+ var block_front: Block
+ if is_chunk_border_face(block.position, Block.Face.BACK):
+ if chunk_exists(grid_position + Vector3i(0, 0, 1)):
+ var chunk_front := Global.chunks[grid_position + Vector3i(0, 0, 1)]
+ if chunk_front.is_inside_tree():
+ block_front = chunk_front.get_block(Vector3i(block.position.x, block.position.y, 0))
+ else:
+ block_front = get_block(block.position + Vector3i(0, 0, 1))
+
+ var block_back: Block
+ if is_chunk_border_face(block.position, Block.Face.FRONT):
+ if chunk_exists(grid_position + Vector3i(0, 0, -1)):
+ var chunk_back := Global.chunks[grid_position + Vector3i(0, 0, -1)]
+ if chunk_back.is_inside_tree():
+ block_back = chunk_back.get_block(Vector3i(
+ block.position.x, block.position.y, Global.CHUNK_SIZE.z - 1)
+ )
+ else:
+ block_back = get_block(block.position + Vector3i(0, 0, -1))
+
+ var block_right: Block
+ if is_chunk_border_face(block.position, Block.Face.RIGHT):
+ if chunk_exists(grid_position + Vector3i(1, 0, 0)):
+ var chunk_right := Global.chunks[grid_position + Vector3i(1, 0, 0)]
+ if chunk_right.is_inside_tree():
+ block_right = chunk_right.get_block(Vector3i(0, block.position.y, block.position.z))
+ else:
+ block_right = get_block(block.position + Vector3i(1, 0, 0))
+
+ var block_left: Block
+ if is_chunk_border_face(block.position, Block.Face.LEFT):
+ if chunk_exists(grid_position + Vector3i(-1, 0, 0)):
+ var chunk_left := Global.chunks[grid_position + Vector3i(-1, 0, 0)]
+ if chunk_left.is_inside_tree():
+ block_left = chunk_left.get_block(Vector3i(
+ Global.CHUNK_SIZE.x - 1, block.position.y, block.position.z)
+ )
+ else:
+ block_left = get_block(block.position + Vector3i(-1, 0, 0))
+
+ var block_top: Block
+ if is_chunk_border_face(block.position, Block.Face.TOP):
+ if chunk_exists(grid_position + Vector3i(0, 1, 0)):
+ var chunk_top := Global.chunks[grid_position + Vector3i(0, 1, 0)]
+ if chunk_top.is_inside_tree():
+ block_top = chunk_top.get_block(Vector3i(block.position.x, 0, block.position.z))
+ else:
+ block_top = get_block(block.position + Vector3i(0, 1, 0))
+
+ var block_bottom: Block
+ if is_chunk_border_face(block.position, Block.Face.BOTTOM):
+ if chunk_exists(grid_position + Vector3i(0, -1, 0)):
+ var chunk_bottom := Global.chunks[grid_position + Vector3i(0, -1, 0)]
+ if chunk_bottom.is_inside_tree():
+ block_bottom = chunk_bottom.get_block(Vector3i(
+ block.position.x, Global.CHUNK_SIZE.y - 1, block.position.z)
+ )
+ else:
+ block_bottom = get_block(block.position + Vector3i(0, -1, 0))
+
+ if not block.type == Block.Type.AIR:
+ if block.type == Block.Type.GRASS:
+ if block_top and block_top.type != Block.Type.AIR:
+ block.type = Block.Type.DIRT
+ elif block.type == Block.Type.DIRT:
+ if not block_top or block_top.type == Block.Type.AIR:
+ block.type = Block.Type.GRASS
+
+ var rng = RandomNumberGenerator.new()
+ rng.seed = randi()
+ st.set_color(Color(rng.randf(), rng.randf(), rng.randf()))
+
+ st.set_uv(Vector2(0, 0))
+
+ if not block_front or block_front.type == Block.Type.AIR:
+ block.add_face(st, Block.Face.FRONT)
+
+ if not block_back or block_back.type == Block.Type.AIR:
+ block.add_face(st, Block.Face.BACK)
+
+ if not block_right or block_right.type == Block.Type.AIR:
+ block.add_face(st, Block.Face.RIGHT)
+
+ if not block_left or block_left.type == Block.Type.AIR:
+ block.add_face(st, Block.Face.LEFT)
+
+ if not block_top or block_top.type == Block.Type.AIR:
+ block.add_face(st, Block.Face.TOP)
+
+ if not block_bottom or block_bottom.type == Block.Type.AIR:
+ block.add_face(st, Block.Face.BOTTOM)
#st.generate_normals()
- var mesh = MeshInstance3D.new()
- mesh.mesh = st.commit()
- mesh.create_trimesh_collision()
+ mesh = st.commit()
+
+
+func update_mesh() -> void:
+ $MeshInstance3D.mesh = mesh
+
+ var shape := ConcavePolygonShape3D.new()
+ var faces := mesh.get_faces()
+ if faces.size() > 0:
+ shape.set_faces(mesh.get_faces())
+ $StaticBody3D/CollisionShape3D.shape = shape
+
+
+func add_to(node: Node) -> void:
+ name = "Chunk_%s_%s_%s" % [grid_position.x, grid_position.y, grid_position.z]
+ node.add_child(self, true)
+ update_mesh()
+
+
+func generate_chunk(row: int, column: int, depth: int):
+ if blocks.is_empty():
+ generate_block_data(row, column, depth)
+
+ generate_mesh()
+
+
+func add_block(block_position: Vector3, block_type: Block.Type = Block.Type.GRASS) -> void:
+ var block = Block.new()
+ block.position = Vector3i(block_position)
+ block.global_position = Vector3i(
+ grid_position.x * Global.CHUNK_SIZE.x + block.position.x,
+ grid_position.y * Global.CHUNK_SIZE.y + block.position.y,
+ grid_position.z * Global.CHUNK_SIZE.z + block.position.z
+ )
+ block.type = block_type
+
+ #blocks[block_position.x][block_position.y][block_position.z] = block
+ set_block(block.position, block)
+ #generate_mesh.call_deferred()
+
+
+func remove_block(block_position: Vector3) -> void:
+ #blocks[block_position.x][block_position.y][block_position.z].type = Block.Type.AIR
+ var block := get_block(block_position)
+ block.type = Block.Type.AIR
+ set_block(block.position, block)
+ print(block_position)
+
+
+func get_block(p: Vector3i) -> Block:
+ return blocks[p.x + Global.CHUNK_SIZE.x * p.y + Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * p.z]
+
+func set_block(p: Vector3i, block: Block) -> void:
+ blocks[p.x + Global.CHUNK_SIZE.x * p.y + Global.CHUNK_SIZE.x * Global.CHUNK_SIZE.y * p.z] = block
+
+
+static func chunk_exists(chunk_position: Vector3i):
+ return Global.chunks.has(chunk_position)
+ #return x >= 0 and chunks.size() - 1 >= x and y >= 0 and chunks[x].size() - 1 >= y and z >= 0 and chunks[x][y].size() - 1 >= z
+
+func block_exists(x: int, y: int, z: int):
+ return x >= 0 and blocks.size() - 1 >= x and y >= 0 and blocks[x].size() - 1 >= y and z >= 0 and blocks[x][y].size() - 1 >= z
+
+func is_chunk_border(p: Vector3i):
+ return p.x == 0 or p.x == Global.CHUNK_SIZE.x - 1 or p.y == 0 or p.y == Global.CHUNK_SIZE.y - 1 or p.z == 0 or p.z == Global.CHUNK_SIZE.z - 1
+
+func is_chunk_border_face(block_position: Vector3i, face: Block.Face) -> bool:
+ if face == Block.Face.FRONT:
+ return block_position.z == 0
+ elif face == Block.Face.BACK:
+ return block_position.z == Global.CHUNK_SIZE.z - 1
+ elif face == Block.Face.LEFT:
+ return block_position.x == 0
+ elif face == Block.Face.RIGHT:
+ return block_position.x == Global.CHUNK_SIZE.z - 1
+ elif face == Block.Face.BOTTOM:
+ return block_position.y == 0
+ elif face == Block.Face.TOP:
+ return block_position.y == Global.CHUNK_SIZE.y - 1
+
+ return false
+
+func get_bordering_chunks(block_position: Vector3i) -> Array[Vector3i]:
+ var bordering_chunks := [] as Array[Vector3i]
+
+ if not is_chunk_border(block_position):
+ return bordering_chunks
+
+ if block_position.z == 0:
+ bordering_chunks.append(grid_position + Vector3i(0, 0, -1))
+ elif block_position.z == Global.CHUNK_SIZE.z - 1:
+ bordering_chunks.append(grid_position + Vector3i(0, 0, 1))
+
+ if block_position.x == 0:
+ bordering_chunks.append(grid_position + Vector3i(-1, 0, 0))
+ elif block_position.x == Global.CHUNK_SIZE.x - 1:
+ bordering_chunks.append(grid_position + Vector3i(1, 0, 0))
+
+ if block_position.y == 0:
+ bordering_chunks.append(grid_position + Vector3i(0, -1, 0))
+ elif block_position.y == Global.CHUNK_SIZE.y - 1:
+ bordering_chunks.append(grid_position + Vector3i(0, 1, 0))
+
+ return bordering_chunks
+
+func get_neighboring_blocks(_block_position: Vector3i) -> Array[Vector3i]:
+ return []
+
+
+@warning_ignore("shadowed_variable_base_class")
+static func global_to_chunk(global_position: Vector3, normal: Vector3) -> Vector3i:
+ return floor((global_position - normal * (Block.BLOCK_SIZE * 0.5)) / Vector3(Global.CHUNK_SIZE))
+
+@warning_ignore("shadowed_variable_base_class")
+static func global_to_chunk_block(global_position: Vector3, normal: Vector3) -> Vector3i:
+ return global_to_block(global_position, normal) - Global.CHUNK_SIZE * global_to_chunk(global_position, normal)
+
+@warning_ignore("shadowed_variable_base_class")
+static func global_to_block(global_position: Vector3, normal: Vector3) -> Vector3i:
+ return floor(global_position - normal * (Block.BLOCK_SIZE * 0.5))
diff --git a/chunk.gd.uid b/chunk.gd.uid
new file mode 100644
index 0000000..897e2c0
--- /dev/null
+++ b/chunk.gd.uid
@@ -0,0 +1 @@
+uid://cdje7x0r2xw8t
diff --git a/chunk.tscn b/chunk.tscn
new file mode 100644
index 0000000..4f50d5b
--- /dev/null
+++ b/chunk.tscn
@@ -0,0 +1,15 @@
+[gd_scene load_steps=3 format=3 uid="uid://e0kmmy52hfp8"]
+
+[ext_resource type="Script" uid="uid://cdje7x0r2xw8t" path="res://chunk.gd" id="1_kdh3y"]
+
+[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_kdh3y"]
+
+[node name="Chunk" type="Node3D"]
+script = ExtResource("1_kdh3y")
+
+[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
+
+[node name="StaticBody3D" type="StaticBody3D" parent="."]
+
+[node name="CollisionShape3D" type="CollisionShape3D" parent="StaticBody3D"]
+shape = SubResource("ConcavePolygonShape3D_kdh3y")
diff --git a/free-look-camera.gd b/free-look-camera.gd
index e35485f..50c2311 100644
--- a/free-look-camera.gd
+++ b/free-look-camera.gd
@@ -30,6 +30,14 @@ var _shift = false
var _alt = false
func _input(event):
+ if not current:
+ return
+
+ 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
+
# Receives mouse motion
if event is InputEventMouseMotion:
_mouse_position = event.relative
@@ -66,6 +74,9 @@ func _input(event):
# Updates mouselook and movement every frame
func _process(delta):
+ if not current:
+ return
+
_update_mouselook()
_update_movement(delta)
diff --git a/free-look-camera.gd.uid b/free-look-camera.gd.uid
new file mode 100644
index 0000000..8baa074
--- /dev/null
+++ b/free-look-camera.gd.uid
@@ -0,0 +1 @@
+uid://cpujedcq8ihr
diff --git a/global.gd b/global.gd
new file mode 100644
index 0000000..96d41c0
--- /dev/null
+++ b/global.gd
@@ -0,0 +1,10 @@
+extends Node
+
+
+var player: Player
+var mutex := Mutex.new()
+
+var chunks: Dictionary[Vector3i, Chunk] = {}
+var CHUNK_SIZE := Vector3i(16, 16, 16)
+var GROUND_LEVEL := 0
+var MAX_HEIGHT := 15
diff --git a/global.gd.uid b/global.gd.uid
new file mode 100644
index 0000000..1504ca8
--- /dev/null
+++ b/global.gd.uid
@@ -0,0 +1 @@
+uid://bfo2qfm7kxid7
diff --git a/inventory_bar.gd b/inventory_bar.gd
new file mode 100644
index 0000000..3f9bda3
--- /dev/null
+++ b/inventory_bar.gd
@@ -0,0 +1,43 @@
+extends Control
+
+
+var active_type: Block.Type = Block.Type.GRASS
+
+
+func _input(event: InputEvent) -> void:
+ if event.is_action_pressed("inventory_bar_slot_1"):
+ _on_texture_rect_pressed()
+ if event.is_action_pressed("inventory_bar_slot_2"):
+ _on_texture_rect_2_pressed()
+ if event.is_action_pressed("inventory_bar_slot_3"):
+ _on_texture_rect_3_pressed()
+ if event.is_action_pressed("inventory_bar_slot_4"):
+ _on_texture_rect_4_pressed()
+ if event.is_action_pressed("inventory_bar_slot_5"):
+ _on_texture_rect_5_pressed()
+ if event.is_action_pressed("inventory_bar_slot_6"):
+ _on_texture_rect_6_pressed()
+
+
+func _on_texture_rect_pressed() -> void:
+ active_type = Block.Type.GRASS
+
+
+func _on_texture_rect_2_pressed() -> void:
+ active_type = Block.Type.STONE
+
+
+func _on_texture_rect_3_pressed() -> void:
+ active_type = Block.Type.ICE
+
+
+func _on_texture_rect_4_pressed() -> void:
+ active_type = Block.Type.WOOD
+
+
+func _on_texture_rect_5_pressed() -> void:
+ active_type = Block.Type.SAND
+
+
+func _on_texture_rect_6_pressed() -> void:
+ active_type = Block.Type.PLANKS
diff --git a/inventory_bar.gd.uid b/inventory_bar.gd.uid
new file mode 100644
index 0000000..e098ba8
--- /dev/null
+++ b/inventory_bar.gd.uid
@@ -0,0 +1 @@
+uid://cmdqh0objlqre
diff --git a/main.gd b/main.gd
index ae29028..ba3d146 100644
--- a/main.gd
+++ b/main.gd
@@ -1,277 +1,136 @@
-class_name Main
+class_name World
extends Node3D
-var chunk_size := Vector3(16, 16, 16)
-
@onready var noise := FastNoiseLite.new()
-var face_corners = [
- Vector2(0, 0), Vector2(1, 0),
- Vector2(0, 1), Vector2(1, 1),
-]
-
-enum BlockFace {
- FRONT,
- BACK,
- LEFT,
- RIGHT,
- TOP,
- BOTTOM,
-}
-var block_faces = [
- [ # FRONT
- [Vector3(-1.0, 1.0, 1.0), Vector3(1.0, -1.0, 1.0), Vector3(-1.0, -1.0, 1.0)],
- [Vector3(-1.0, 1.0, 1.0), Vector3(1.0, 1.0, 1.0), Vector3(1.0, -1.0, 1.0)],
- ],
- [ # BACK
- [Vector3(1.0, 1.0, -1.0), Vector3(-1.0, -1.0, -1.0), Vector3(1.0, -1.0, -1.0)],
- [Vector3(1.0, 1.0, -1.0), Vector3(-1.0, 1.0, -1.0), Vector3(-1.0, -1.0, -1.0)],
- ],
- [ # LEFT
- [Vector3(-1.0, 1.0, -1.0), Vector3(-1.0, -1.0, 1.0), Vector3(-1.0, -1.0, -1.0)],
- [Vector3(-1.0, 1.0, -1.0), Vector3(-1.0, 1.0, 1.0), Vector3(-1.0, -1.0, 1.0)],
- ],
- [ # RIGHT
- [Vector3(1.0, 1.0, 1.0), Vector3(1.0, -1.0, -1.0), Vector3(1.0, -1.0, 1.0)],
- [Vector3(1.0, 1.0, 1.0), Vector3(1.0, 1.0, -1.0), Vector3(1.0, -1.0, -1.0)],
- ],
- [ # TOP
- [Vector3(-1.0, 1.0, -1.0), Vector3(1.0, 1.0, 1.0), Vector3(-1.0, 1.0, 1.0)],
- [Vector3(-1.0, 1.0, -1.0), Vector3(1.0, 1.0, -1.0), Vector3(1.0, 1.0, 1.0)],
- ],
- [ # BOTTOM
- [Vector3(-1.0, -1.0, 1.0), Vector3(1.0, -1.0, -1.0), Vector3(-1.0, -1.0, -1.0)],
- [Vector3(-1.0, -1.0, 1.0), Vector3(1.0, -1.0, 1.0), Vector3(1.0, -1.0, -1.0)],
- ],
-]
-var block_face_uvs = [
- [ # FRONT
- [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)],
- [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)],
- ],
- [ # BACK
- [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)],
- [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)],
- ],
- [ # LEFT
- [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)],
- [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)],
- ],
- [ # RIGHT
- [Vector2(0.0, 0.0), Vector2(1.0, 1.0), Vector2(0.0, 1.0)],
- [Vector2(0.0, 0.0), Vector2(1.0, 0.0), Vector2(1.0, 1.0)],
- ],
- [ # TOP
- [Vector2(0.0, 1.0), Vector2(1.0, 2.0), Vector2(0.0, 2.0)],
- [Vector2(0.0, 1.0), Vector2(1.0, 1.0), Vector2(1.0, 2.0)],
- ],
- [ # BOTTOM
- [Vector2(1.0, 0.0), Vector2(2.0, 1.0), Vector2(1.0, 1.0)],
- [Vector2(1.0, 0.0), Vector2(2.0, 0.0), Vector2(2.0, 1.0)],
- ],
-]
-var block_face_normals = [
- Vector3(0, 0, 1), # FRONT
- Vector3(0, 0, -1), # BACK
- Vector3(-1, 0, 0), # LEFT
- Vector3(1, 0, 0), # RIGHT
- Vector3(0, 1, 0), # TOP
- Vector3(0, -1, 0), # BOTTOM
-]
+var chunks_to_generate: Array[Vector3i] = []
+var chunks_to_update: Array[Vector3i] = []
+var active_generate_task_id: int = -1
+var active_update_task_id: int = -1
-enum BlockType {
- AIR,
- GRASS,
- DIRT,
- LEAVES,
- STONE,
-}
-var block_types = {
- BlockType.GRASS: {
- "uv2s": [
- Vector2(0, 0), # FRONT
- Vector2(0, 0), # BACK
- Vector2(0, 0), # LEFT
- Vector2(0, 0), # RIGHT
- Vector2(0, 1), # TOP
- Vector2(1, 0), # BOTTOM
- ],
- },
- BlockType.DIRT: {
- "uv2s": [
- Vector2(1, 0), # FRONT
- Vector2(1, 0), # BACK
- Vector2(1, 0), # LEFT
- Vector2(1, 0), # RIGHT
- Vector2(1, 0), # TOP
- Vector2(1, 0), # BOTTOM
- ],
- },
- BlockType.LEAVES: {
- "uv2s": [
- Vector2(2, 2), # FRONT
- Vector2(2, 2), # BACK
- Vector2(2, 2), # LEFT
- Vector2(2, 2), # RIGHT
- Vector2(2, 2), # TOP
- Vector2(2, 2), # BOTTOM
- ],
- },
- BlockType.STONE: {
- "uv2s": [
- Vector2(2, 0), # FRONT
- Vector2(2, 0), # BACK
- Vector2(2, 0), # LEFT
- Vector2(2, 0), # RIGHT
- Vector2(2, 0), # TOP
- Vector2(2, 0), # BOTTOM
- ],
- },
-}
+var player_last_chunk := Vector3i.ZERO
+var chunk_generation_radius := Vector3i(2, 2, 2)
-var chunks := []
+@onready var chunks_container := $Chunks
func _ready() -> void:
- brrr()
-
-
-class OtherThread extends Thread:
- func _exit_tree():
- wait_to_finish()
-
-
-func brrr():
+ Global.player = $Player
noise.seed = randi()
- var thread = OtherThread.new()
- var rrrb = func():
- for row in range(0, 8):
- chunks.append([])
- for column in range(0, 4):
- chunks[row].append([])
- for depth in range(0, 8):
- chunks[row][column].append([])
- generate_chunk(row, column, depth)
+ var world_size := Vector3i(2, 1, 2)
- thread.start(rrrb)
- #thread.wait_to_finish()
+ for column in range(world_size.y, 0, -1):
+ for row in range(- world_size.x * 0.5, world_size.x * 0.5):
+ for depth in range(- world_size.z * 0.5, world_size.z * 0.5):
+ chunks_to_generate.append(Vector3i(row, column, depth))
+
+ # TODO: 2*1*2 worldgen on main thread
+ # TODO: show loading anim. how?
+ # TODO: worldgen not on main thread.
+ # TODO: get number of chunks to be gen
+ # TODO: ++number and show progress %
-func generate_chunk(row, column, depth):
- #var material := StandardMaterial3D.new()
- #material.albedo_texture = preload("res://new_atlas_texture.tres")
- #material.vertex_color_use_as_albedo = true
- var material := preload("res://new_shader_material.tres")
- var st = SurfaceTool.new()
- st.begin(Mesh.PRIMITIVE_TRIANGLES)
- st.set_material(material)
-
- var blocks = []
-
- for x in chunk_size.x:
- #blocks[x] = []
- blocks.append([])
- for y in chunk_size.y:
- #blocks[x][y] = []
- blocks[x].append([])
- for z in chunk_size.z:
- var block_position = Vector3(
- row*chunk_size.x + x,
- column*chunk_size.y + y,
- depth*chunk_size.z + z
- #x,
- #y,
- #z
- ) * 2
- var value = noise.get_noise_3d(block_position.x, block_position.y, block_position.z) * 100
-
- var type = BlockType.AIR
- if value > -15:
- type = BlockType.GRASS
- elif value > -20:
- type = BlockType.STONE
-
- var block = {
- "position": block_position,
- "type": type,
- }
- #blocks[x][y][z] = block_position
- blocks[x][y].append(block)
-
- for x in blocks.size():
- for y in blocks[x].size():
- for z in blocks[x][y].size():
- var block = blocks[x][y][z]
- var block_position = block.position
-
- if not block.type == BlockType.AIR:
- if block.type == BlockType.GRASS and blocks[x].size() > y + 1 and not blocks[x][y + 1][z].type == BlockType.AIR:
- block.type = BlockType.DIRT
-
- var rng = RandomNumberGenerator.new()
- rng.seed = randi()
- st.set_color(Color(rng.randf(), rng.randf(), rng.randf()))
-
- st.set_uv(Vector2(0, 0))
-
- if (blocks[x][y].size() > z+1 and blocks[x][y][z + 1].type == BlockType.AIR) or blocks[x][y].size() == z+1:
- add_face(st, BlockFace.FRONT, block)
-
- if (blocks.size() > x+1 and blocks[x + 1][y][z].type == BlockType.AIR) or blocks.size() == x+1:
- add_face(st, BlockFace.RIGHT, block)
-
- if blocks[x][y].size() > z-1 and (blocks[x][y][z - 1].type == BlockType.AIR or z == 0):
- add_face(st, BlockFace.BACK, block)
-
- if blocks.size() > x-1 and (blocks[x - 1][y][z].type == BlockType.AIR or x == 0):
- add_face(st, BlockFace.LEFT, block)
-
- if (blocks[x].size() > y+1 and blocks[x][y + 1][z].type == BlockType.AIR) or blocks[x].size() == y+1:
- add_face(st, BlockFace.TOP, block)
-
- if blocks[x].size() > y-1 and (blocks[x][y - 1][z].type == BlockType.AIR or y == 0):
- add_face(st, BlockFace.BOTTOM, block)
-
- chunks[row][column][depth] = blocks
+func _process(_delta: float) -> void:
+ if chunks_to_generate.size() > 0:
+ if active_generate_task_id == -1:
+ active_generate_task_id = WorkerThreadPool.add_task(generate_chunk_task.bind(0))
+ else:
+ if WorkerThreadPool.is_task_completed(active_generate_task_id):
+ WorkerThreadPool.wait_for_task_completion(active_generate_task_id)
+ chunks_to_generate.remove_at(0)
+ active_generate_task_id = -1
- #st.generate_normals()
- var mesh = MeshInstance3D.new()
- mesh.mesh = st.commit()
- mesh.create_trimesh_collision()
- add_child.call_deferred(mesh)
+ if chunks_to_update.size() > 0:
+ if active_update_task_id == -1:
+ active_update_task_id = WorkerThreadPool.add_group_task(update_chunk_task, chunks_to_update.size())
+ else:
+ if WorkerThreadPool.is_group_task_completed(active_update_task_id):
+ WorkerThreadPool.wait_for_group_task_completion(active_update_task_id)
+ chunks_to_update.remove_at(0)
+ active_update_task_id = -1
+
+
+func _physics_process(_delta: float) -> void:
+ if player_last_chunk != Global.player.current_chunk_position:
+ player_last_chunk = Global.player.current_chunk_position
+ var chunks_in_radius := []
+ for x in range(- chunk_generation_radius.x * 0.5, chunk_generation_radius.x * 0.5 + 1):
+ for y in range(- chunk_generation_radius.y * 0.5, chunk_generation_radius.y * 0.5 + 1):
+ for z in range(- chunk_generation_radius.z * 0.5, chunk_generation_radius.z * 0.5 + 1):
+ var chunk_to_check := Global.player.current_chunk_position + Vector3i(x, y, z)
+ chunks_in_radius.append(chunk_to_check)
+
+ # generate new or re-generate existing nodes
+ for p in chunks_in_radius:
+ if not Chunk.chunk_exists(p):
+ chunks_to_generate.append(p)
+ elif not chunks_container.has_node("Chunk_%s_%s_%s" % [p.x, p.y, p.z]):
+ chunks_to_generate.append(p)
+
+ # remove surplus nodes
+ for node: Chunk in chunks_container.get_children():
+ if not chunks_in_radius.has(node.grid_position):
+ chunks_container.remove_child(node)
-# Called every frame. 'delta' is the elapsed time since the previous frame.
-func _process(_delta: float) -> void:
- pass
+func generate_chunk_task(index: int) -> void:
+ update_chunk(chunks_to_generate[index])
+func update_chunk_task(index: int) -> void:
+ update_chunk(chunks_to_update[index])
-func add_face(surface_tool: SurfaceTool, face: BlockFace, block: Dictionary):
- var block_position: Vector3 = block.position
- var type: BlockType = block.type
+func update_chunk(chunk_position: Vector3i) -> void:
+ if Chunk.chunk_exists(chunk_position):
+ var chunk: Chunk = Global.chunks[chunk_position]
+ chunk.generate_mesh()
+ chunk.update_mesh.call_deferred()
+
+ (func():
+ if not chunks_container.has_node("Chunk_%s_%s_%s" % [chunk_position.x, chunk_position.y, chunk_position.z]):
+ chunk.add_to(chunks_container)
+ ).call_deferred()
- var uv2s = []
- uv2s.resize(3)
- uv2s.fill(block_types[type].uv2s[face])
+ else:
+ var chunk := create_chunk(chunk_position)
+ chunk.generate_block_data(chunk_position.x, chunk_position.y, chunk_position.z)
+ chunk.generate_mesh()
+ chunk.add_to.call_deferred(chunks_container)
+
+
+func create_chunk(chunk_position: Vector3i) -> Chunk:
+ var chunk: Chunk = preload("res://chunk.tscn").instantiate()
+ chunk.noise = noise
+ Global.chunks[chunk_position] = chunk
- var normals = []
- normals.resize(3)
- normals.fill(block_face_normals[face])
+ return chunk
+
+
+func add_block(target_position: Vector3, normal: Vector3, block_type: Block.Type = Block.Type.AIR):
+ var chunk_idx := Chunk.global_to_chunk(target_position + normal, Vector3.ZERO)
+ var chunk: Chunk
- for idx in block_faces[face].size():
- var triangle = block_faces[face][idx]
- var triangle_positions = triangle.map(func(item):
- return item + block_position
- )
-
- var uvs = block_face_uvs[face][idx]
-
- surface_tool.add_triangle_fan(
- PackedVector3Array(triangle_positions),
- PackedVector2Array(uvs),
- PackedColorArray(),
- PackedVector2Array(uv2s),
- PackedVector3Array(normals)
- )
+ if Chunk.chunk_exists(chunk_idx):
+ chunk = Global.chunks[chunk_idx]
+ else:
+ chunk = create_chunk(Vector3(chunk_idx.x, chunk_idx.y, chunk_idx.z))
+ chunk.generate_block_data(chunk_idx.x, chunk_idx.y, chunk_idx.z, true)
+ chunk.add_to.call_deferred(self)
+
+ var block_chunk_idx := Chunk.global_to_chunk_block(target_position + normal, normal)
+ chunk.add_block(block_chunk_idx, block_type)
+ chunks_to_update.append(chunk.grid_position)
+
+
+func remove_block(target_position: Vector3, normal: Vector3):
+ var chunk_idx := Chunk.global_to_chunk(target_position, normal)
+ if Chunk.chunk_exists(chunk_idx):
+ var chunk: Chunk = Global.chunks[chunk_idx]
+ var block_chunk_idx := Chunk.global_to_chunk_block(target_position, normal)
+ chunk.remove_block(block_chunk_idx)
+ chunks_to_update.append(chunk.grid_position)
+ chunks_to_update.append_array(chunk.get_bordering_chunks(block_chunk_idx).filter(func(item):
+ return Chunk.chunk_exists(item)
+ ))
diff --git a/main.gd.uid b/main.gd.uid
new file mode 100644
index 0000000..e97d76c
--- /dev/null
+++ b/main.gd.uid
@@ -0,0 +1 @@
+uid://b7wxthju54wyu
diff --git a/main.tscn b/main.tscn
index b25da59..804963c 100644
--- a/main.tscn
+++ b/main.tscn
@@ -1,8 +1,11 @@
-[gd_scene load_steps=8 format=3 uid="uid://b7k6l3bm1f0db"]
+[gd_scene load_steps=18 format=3 uid="uid://b7k6l3bm1f0db"]
-[ext_resource type="Script" path="res://main.gd" id="1_g4bmv"]
+[ext_resource type="Script" uid="uid://b7wxthju54wyu" path="res://main.gd" id="1_g4bmv"]
+[ext_resource type="Script" uid="uid://cpujedcq8ihr" path="res://free-look-camera.gd" id="2_4jusq"]
[ext_resource type="Texture2D" uid="uid://dv842eajslxyw" path="res://icon.svg" id="3_7tj3h"]
-[ext_resource type="Script" path="res://player.gd" id="3_tn7lj"]
+[ext_resource type="Script" uid="uid://bvlgfeu5rty6x" path="res://player.gd" id="3_tn7lj"]
+[ext_resource type="Script" uid="uid://cmdqh0objlqre" path="res://inventory_bar.gd" id="5_c1toa"]
+[ext_resource type="Texture2D" uid="uid://ld8e4g6oef3x" path="res://Spritesheet.png" id="5_dqy55"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_vv2it"]
sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1)
@@ -18,6 +21,40 @@ tonemap_mode = 2
glow_enabled = true
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_cggfi"]
+radius = 0.45
+height = 1.8
+
+[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_4b324"]
+bg_color = Color(0.18359, 0.18359, 0.18359, 1)
+border_width_left = 4
+border_width_top = 4
+border_width_right = 4
+border_width_bottom = 4
+border_color = Color(0.184314, 0.184314, 0.184314, 1)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_w53vy"]
+atlas = ExtResource("5_dqy55")
+region = Rect2(0, 0, 80, 80)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_kv0hd"]
+atlas = ExtResource("5_dqy55")
+region = Rect2(160, 0, 80, 80)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_46jgo"]
+atlas = ExtResource("5_dqy55")
+region = Rect2(160, 80, 80, 80)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_pooo8"]
+atlas = ExtResource("5_dqy55")
+region = Rect2(400, 0, 80, 80)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_ikpm6"]
+atlas = ExtResource("5_dqy55")
+region = Rect2(320, 0, 80, 80)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_vqce1"]
+atlas = ExtResource("5_dqy55")
+region = Rect2(0, 160, 80, 80)
[node name="Main" type="Node3D"]
script = ExtResource("1_g4bmv")
@@ -33,37 +70,90 @@ directional_shadow_max_distance = 400.0
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.767031, 0.64161, 0, -0.64161, 0.767031, 0.387164, 18.7811, 29.7854)
-current = true
+script = ExtResource("2_4jusq")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
-[node name="CharacterBody3D" type="CharacterBody3D" parent="."]
-transform = Transform3D(-0.0770845, 0, 0.997025, 0, 1, 0, -0.997025, 0, -0.0770845, 0, 238.895, 0)
+[node name="Chunks" type="Node3D" parent="."]
+
+[node name="Player" type="CharacterBody3D" parent="." groups=["player"]]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8, 16, 2)
script = ExtResource("3_tn7lj")
-[node name="CollisionShape3D" type="CollisionShape3D" parent="CharacterBody3D"]
+[node name="CollisionShape3D" type="CollisionShape3D" parent="Player"]
shape = SubResource("CapsuleShape3D_cggfi")
-[node name="CameraAnchor" type="Marker3D" parent="CharacterBody3D"]
+[node name="CameraAnchor" type="Marker3D" parent="Player"]
transform = Transform3D(0.999999, 0, 0, 0, 1, 0, 7.45058e-09, 0, 1, 0, 0.87, 0)
-[node name="Camera" type="Camera3D" parent="CharacterBody3D/CameraAnchor"]
+[node name="Camera" type="Camera3D" parent="Player/CameraAnchor"]
current = true
-[node name="RayCast3D" type="RayCast3D" parent="CharacterBody3D/CameraAnchor/Camera"]
+[node name="RayCast3D" type="RayCast3D" parent="Player/CameraAnchor/Camera"]
target_position = Vector3(0, 0, -5)
-[node name="CanvasLayer" type="CanvasLayer" parent="CharacterBody3D"]
+[node name="CanvasLayer" type="CanvasLayer" parent="Player"]
-[node name="CenterContainer" type="CenterContainer" parent="CharacterBody3D/CanvasLayer"]
+[node name="CenterContainer" type="CenterContainer" parent="Player/CanvasLayer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
-[node name="TextureRect" type="TextureRect" parent="CharacterBody3D/CanvasLayer/CenterContainer"]
+[node name="TextureRect" type="TextureRect" parent="Player/CanvasLayer/CenterContainer"]
custom_minimum_size = Vector2(16, 16)
layout_mode = 2
texture = ExtResource("3_7tj3h")
expand_mode = 1
+
+[node name="MarginContainer" type="MarginContainer" parent="Player/CanvasLayer"]
+anchors_preset = 12
+anchor_top = 1.0
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 0
+theme_override_constants/margin_bottom = 4
+script = ExtResource("5_c1toa")
+
+[node name="CenterContainer" type="CenterContainer" parent="Player/CanvasLayer/MarginContainer"]
+layout_mode = 2
+
+[node name="PanelContainer" type="PanelContainer" parent="Player/CanvasLayer/MarginContainer/CenterContainer"]
+layout_mode = 2
+theme_override_styles/panel = SubResource("StyleBoxFlat_4b324")
+
+[node name="HBoxContainer" type="HBoxContainer" parent="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer"]
+layout_mode = 2
+
+[node name="TextureRect" type="TextureButton" parent="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer"]
+layout_mode = 2
+texture_normal = SubResource("AtlasTexture_w53vy")
+
+[node name="TextureRect2" type="TextureButton" parent="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer"]
+layout_mode = 2
+texture_normal = SubResource("AtlasTexture_kv0hd")
+
+[node name="TextureRect3" type="TextureButton" parent="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer"]
+layout_mode = 2
+texture_normal = SubResource("AtlasTexture_46jgo")
+
+[node name="TextureRect4" type="TextureButton" parent="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer"]
+layout_mode = 2
+texture_normal = SubResource("AtlasTexture_pooo8")
+
+[node name="TextureRect5" type="TextureButton" parent="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer"]
+layout_mode = 2
+texture_normal = SubResource("AtlasTexture_ikpm6")
+
+[node name="TextureRect6" type="TextureButton" parent="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer"]
+layout_mode = 2
+texture_normal = SubResource("AtlasTexture_vqce1")
+
+[connection signal="pressed" from="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer/TextureRect" to="Player/CanvasLayer/MarginContainer" method="_on_texture_rect_pressed"]
+[connection signal="pressed" from="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer/TextureRect2" to="Player/CanvasLayer/MarginContainer" method="_on_texture_rect_2_pressed"]
+[connection signal="pressed" from="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer/TextureRect3" to="Player/CanvasLayer/MarginContainer" method="_on_texture_rect_3_pressed"]
+[connection signal="pressed" from="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer/TextureRect4" to="Player/CanvasLayer/MarginContainer" method="_on_texture_rect_4_pressed"]
+[connection signal="pressed" from="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer/TextureRect5" to="Player/CanvasLayer/MarginContainer" method="_on_texture_rect_5_pressed"]
+[connection signal="pressed" from="Player/CanvasLayer/MarginContainer/CenterContainer/PanelContainer/HBoxContainer/TextureRect6" to="Player/CanvasLayer/MarginContainer" method="_on_texture_rect_6_pressed"]
diff --git a/new_shader.gdshader b/new_shader.gdshader
index e9d2a08..5087a7a 100644
--- a/new_shader.gdshader
+++ b/new_shader.gdshader
@@ -3,6 +3,8 @@ shader_type spatial;
uniform sampler2DArray textures : filter_nearest, source_color;
uniform int elements_per_row;
+varying float is_block;
+
void vertex() {
// Called for every vertex the material is visible on.
}
diff --git a/new_shader.gdshader.uid b/new_shader.gdshader.uid
new file mode 100644
index 0000000..e1ba58a
--- /dev/null
+++ b/new_shader.gdshader.uid
@@ -0,0 +1 @@
+uid://j15ms63fqodv
diff --git a/new_shader_material.tres b/new_shader_material.tres
index f01b9b1..b72a259 100644
--- a/new_shader_material.tres
+++ b/new_shader_material.tres
@@ -1,10 +1,10 @@
[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://13gixtegdfat"]
-[ext_resource type="Shader" path="res://new_shader.gdshader" id="1_ux1ye"]
+[ext_resource type="Shader" uid="uid://j15ms63fqodv" path="res://new_shader.gdshader" id="1_ux1ye"]
[ext_resource type="CompressedTexture2DArray" uid="uid://demlxku183noo" path="res://Spritesheet_array.png" id="2_delqc"]
[resource]
render_priority = 0
shader = ExtResource("1_ux1ye")
-shader_parameter/elements_per_row = 6
shader_parameter/textures = ExtResource("2_delqc")
+shader_parameter/elements_per_row = 6
diff --git a/new_shader_material_selection.tres b/new_shader_material_selection.tres
new file mode 100644
index 0000000..da85f8a
--- /dev/null
+++ b/new_shader_material_selection.tres
@@ -0,0 +1,10 @@
+[gd_resource type="ShaderMaterial" load_steps=3 format=3 uid="uid://cgvu2qg8kba3m"]
+
+[ext_resource type="Shader" uid="uid://boveokh7mbuwp" path="res://new_shader_selection.gdshader" id="1_0lbk8"]
+[ext_resource type="CompressedTexture2DArray" uid="uid://demlxku183noo" path="res://Spritesheet_array.png" id="2_xnnyw"]
+
+[resource]
+render_priority = 0
+shader = ExtResource("1_0lbk8")
+shader_parameter/textures = ExtResource("2_xnnyw")
+shader_parameter/elements_per_row = 6
diff --git a/new_shader_selection.gdshader b/new_shader_selection.gdshader
new file mode 100644
index 0000000..513ee92
--- /dev/null
+++ b/new_shader_selection.gdshader
@@ -0,0 +1,23 @@
+shader_type spatial;
+
+uniform sampler2DArray textures : filter_nearest, source_color;
+uniform int elements_per_row;
+
+varying float is_block;
+
+void vertex() {
+ // Called for every vertex the material is visible on.
+}
+
+void fragment() {
+ // Called for every pixel the material is visible on.
+ int index = int(UV2.y) * elements_per_row + int(UV2.x);
+ vec4 element = texture(textures, vec3(UV, float(index)));
+ ALBEDO = element.rgb;
+ ALPHA = element.a;
+}
+
+//void light() {
+ // Called for every pixel for every light affecting the material.
+ // Uncomment to replace the default light processing function with this one.
+//}
diff --git a/new_shader_selection.gdshader.uid b/new_shader_selection.gdshader.uid
new file mode 100644
index 0000000..0e15a33
--- /dev/null
+++ b/new_shader_selection.gdshader.uid
@@ -0,0 +1 @@
+uid://boveokh7mbuwp
diff --git a/player.gd b/player.gd
index cf8e90e..5f0f600 100644
--- a/player.gd
+++ b/player.gd
@@ -1,14 +1,35 @@
+class_name Player
extends CharacterBody3D
-const SPEED = 20.0
-const JUMP_VELOCITY = 20.0
+var selection_block: MeshInstance3D
+var selection_block_data: Block
+var previous_looked_at_block_position: Vector3i = Vector3i.ZERO
+
+var current_chunk_position: Vector3i
+
+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
+ #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
+
+ current_chunk_position = Chunk.global_to_chunk(global_position, Vector3.ZERO)
+ self.set_physics_process(false)
+ await get_tree().create_timer(3.0).timeout
+ self.set_physics_process(true)
func _input(event: InputEvent) -> void:
@@ -17,39 +38,58 @@ func _input(event: InputEvent) -> void:
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:
+func _process(_delta: float) -> void:
if $CameraAnchor/Camera/RayCast3D.is_colliding():
var collider = $CameraAnchor/Camera/RayCast3D.get_collider()
- var point = $CameraAnchor/Camera/RayCast3D.get_collision_point()
-
- var block_idx = floor(point / 2)
- var block_chunk_idx = Vector3(
- int(floor(point.x / 2)) % 16,
- int(floor(point.y / 2)) % 16,
- int(floor(point.z / 2)) % 16
- )
- var chunk_idx = floor(point / (16*2))
+ if collider is not StaticBody3D:
+ return
- acc += delta
- if acc / 5 > 1.0:
- acc = 0
- print(block_chunk_idx)
- print(chunk_idx)
- var chunk = get_tree().current_scene.chunks[chunk_idx.x][chunk_idx.y][chunk_idx.z]
- var block = chunk[block_chunk_idx.x][block_chunk_idx.y][block_chunk_idx.z]
- print(block)
- print(Main.BlockType.keys()[block.type])
+ var point = $CameraAnchor/Camera/RayCast3D.get_collision_point()
+ maybe_update_selection_block(point)
+ else:
+ selection_block.visible = false
func _physics_process(delta: float) -> void:
+ current_chunk_position = Chunk.global_to_chunk(global_position, Vector3.ZERO)
+
# Add the gravity.
if not is_on_floor():
- velocity += get_gravity() * delta
+ velocity += get_gravity() * delta * 1.5
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
@@ -65,10 +105,53 @@ func _physics_process(delta: float) -> void:
.rotated(Vector3(0, 0, 1), $CameraAnchor.rotation.z)
)
if direction:
- velocity.x = direction.x * SPEED
- velocity.z = direction.z * SPEED
+ 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.get_block(block_chunk_idx)
+
+ selection_block.visible = true
+
+ if previous_looked_at_block_position != block.global_position:
+ update_selection_block(block.global_position)
+ previous_looked_at_block_position = block.global_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
+ )
diff --git a/player.gd.uid b/player.gd.uid
new file mode 100644
index 0000000..e0e0efa
--- /dev/null
+++ b/player.gd.uid
@@ -0,0 +1 @@
+uid://bvlgfeu5rty6x
diff --git a/project.godot b/project.godot
index e6bea42..d0a61d0 100644
--- a/project.godot
+++ b/project.godot
@@ -12,9 +12,17 @@ config_version=5
config/name="Minecraft"
run/main_scene="res://main.tscn"
-config/features=PackedStringArray("4.3", "GL Compatibility")
+config/features=PackedStringArray("4.4", "GL Compatibility")
config/icon="res://icon.svg"
+[autoload]
+
+Global="*res://global.gd"
+
+[global_group]
+
+player=""
+
[input]
ui_left={
@@ -69,6 +77,71 @@ mouse_exit={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
+left_click={
+"deadzone": 0.5,
+"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(282, 22),"global_position":Vector2(291, 68),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
+]
+}
+right_click={
+"deadzone": 0.5,
+"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(324, 20),"global_position":Vector2(333, 66),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
+]
+}
+inventory_bar_slot_1={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":49,"key_label":0,"unicode":49,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_2={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":50,"key_label":0,"unicode":50,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_3={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":51,"key_label":0,"unicode":51,"location":0,"echo":false,"script":null)
+]
+}
+run={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_4={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":52,"key_label":0,"unicode":52,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_5={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":53,"key_label":0,"unicode":53,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_6={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":54,"key_label":0,"unicode":54,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_7={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":55,"key_label":0,"unicode":55,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_8={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":56,"key_label":0,"unicode":56,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_9={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":57,"key_label":0,"unicode":57,"location":0,"echo":false,"script":null)
+]
+}
+inventory_bar_slot_10={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":48,"key_label":0,"unicode":48,"location":0,"echo":false,"script":null)
+]
+}
[rendering]