diff options
-rw-r--r-- | Spritesheet_array.png | bin | 6886 -> 6906 bytes | |||
-rw-r--r-- | Spritesheet_array.png~ | bin | 6613 -> 6913 bytes | |||
-rw-r--r-- | block.gd | 118 | ||||
-rw-r--r-- | block.gd.uid | 1 | ||||
-rw-r--r-- | camera.gd.uid | 1 | ||||
-rw-r--r-- | chunk.gd | 353 | ||||
-rw-r--r-- | chunk.gd.uid | 1 | ||||
-rw-r--r-- | chunk.tscn | 15 | ||||
-rw-r--r-- | free-look-camera.gd | 11 | ||||
-rw-r--r-- | free-look-camera.gd.uid | 1 | ||||
-rw-r--r-- | global.gd | 10 | ||||
-rw-r--r-- | global.gd.uid | 1 | ||||
-rw-r--r-- | inventory_bar.gd | 43 | ||||
-rw-r--r-- | inventory_bar.gd.uid | 1 | ||||
-rw-r--r-- | main.gd | 367 | ||||
-rw-r--r-- | main.gd.uid | 1 | ||||
-rw-r--r-- | main.tscn | 116 | ||||
-rw-r--r-- | new_shader.gdshader | 2 | ||||
-rw-r--r-- | new_shader.gdshader.uid | 1 | ||||
-rw-r--r-- | new_shader_material.tres | 4 | ||||
-rw-r--r-- | new_shader_material_selection.tres | 10 | ||||
-rw-r--r-- | new_shader_selection.gdshader | 23 | ||||
-rw-r--r-- | new_shader_selection.gdshader.uid | 1 | ||||
-rw-r--r-- | player.gd | 133 | ||||
-rw-r--r-- | player.gd.uid | 1 | ||||
-rw-r--r-- | project.godot | 75 |
26 files changed, 913 insertions, 377 deletions
diff --git a/Spritesheet_array.png b/Spritesheet_array.png Binary files differindex 82159f8..6e3e519 100644 --- a/Spritesheet_array.png +++ b/Spritesheet_array.png diff --git a/Spritesheet_array.png~ b/Spritesheet_array.png~ Binary files differindex 25a41fb..e6f3299 100644 --- a/Spritesheet_array.png~ +++ b/Spritesheet_array.png~ @@ -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 @@ -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 @@ -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 @@ -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 @@ -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] |