diff --git a/README.md b/README.md index 930892f..ea85f36 100644 --- a/README.md +++ b/README.md @@ -1 +1,24 @@ -# Godot-Voxel-Prototype \ No newline at end of file +# Voxel Prototype + +# Licenses: code: LGPL-2.1, media: CC BY-SA-4.0 +## this is a Godot game project: https://godotengine.org + +![Screenshot](/screenshot.PNG) + +**Notes** + +1. i like to do things simple, the result is more performance + a less confused coder. +1. this was a very early step in my game progress. +1. i dont know why the water looks wierd. +1. i dont know why the player is shaking. +1. i have no desire to make a save game system or update this project anymore. +1. just enyoy + +|Action|Control| +|----|----| +|Move|A,S,D,W,S| +|Jump|Space| +Fly/Walk mode|F| +Fly up/down|Q,E| +Fly slow|SHIFT| +Choose block|scroll up/down| diff --git a/chunk.gd b/chunk.gd new file mode 100644 index 0000000..3d488a0 --- /dev/null +++ b/chunk.gd @@ -0,0 +1,140 @@ +extends Spatial + +var timer = 0 +var chunks_in_progress = {} +var progress2del = {} + +func _init(): + core.chunk=self + +#creates a new chunk array +#adds air to it so the player not reaching a empty space and things craches +func new_chunk(pos): + var id = pos_to_chunkid(pos) + var chunk_pos = to_chunk_pos(pos) + var air = core.get_node_reg("air").id + for x in range(-core.chunk_size/2,core.chunk_size/2): + for y in range(-core.chunk_size/2,core.chunk_size/2): + for z in range(-core.chunk_size/2,core.chunk_size/2): + core.inset_map_node_id(air,chunk_pos+Vector3(x,y,z)) + core.chunks[id] = MeshInstance.new() + var chunk = core.chunks[id] + chunk.transform.origin = chunk_pos + add_child(chunk) + var staticbody = StaticBody.new() + staticbody.name = "body" + chunk.add_child(staticbody) + var collision = CollisionShape.new() + collision.name = "collision" + staticbody.add_child(collision) + +func to_chunk_pos(pos): + var c = core.chunk_size + var s = core.chunk_size/2 + return ((pos+Vector3(s,s,s))/c).floor()*c + +func get_chunk_at_pos(pos): + var c = core.chunk_size + var s = core.chunk_size/2 + var c_pos = ((pos+Vector3(s,s,s))/c).floor() + return core.chunks.get(c_pos) + +func pos_to_chunkid(pos): + var c = core.chunk_size + var s = core.chunk_size/2 + return ((pos+Vector3(s,s,s))/c).floor() + +func get_chunk(id): + return core.chunks.get(id) + +#sends chunks to update in a list to process +#this keeps performance well, even we can expect somewhat slower loading +func _process(delta): + timer += delta + if timer > 0.0: + timer = 0 + + for i in progress2del: + chunks_in_progress.erase(i) + progress2del.clear() + var max_nodes = core.settings.max_update_nodes + for di in chunks_in_progress: + var data = chunks_in_progress.get(di) + var chunk_mesh = get_chunk(data.chunkid) + for x in range(data.range_x.a,data.range_x.b): + for y in range(data.range_y.a,data.range_y.b): + for z in range(data.range_z.a,data.range_z.b): + + max_nodes -= 1 + if max_nodes < 0: + data.range_x.a = x + data.range_y.a = y + data.range_z.a = z + return + + var lpos = Vector3(x,y,z) + var id = core.map.get(lpos+data.chunk_pos) + + if id: + var n = core.register.id.get(id) if id != null else "default" + var reg = core.register.nodes.get(n) + var tile = core.default_texture if reg.tiles.size() < 1 else reg.tiles[0] + if reg.drawtype != "none": + for f in core.default_node.faces.size(): + var neighbour_id = core.map.get(lpos+core.default_node.dir[f]+data.chunk_pos) + var neighbour_name = core.register.id.get(neighbour_id) if neighbour_id != null else "none" + var neighbour_reg = core.register.nodes.get(neighbour_name) + + if (data.full_cubes and neighbour_id == null) or (neighbour_id != id and neighbour_reg.get("solid_surface") == false): + data.st.begin(Mesh.PRIMITIVE_TRIANGLE_FAN) + var mat = SpatialMaterial.new() + var transparent = reg.get("transparent") == true + if f < reg.tiles.size(): + tile = reg.tiles[f] + mat.albedo_texture = tile + mat.flags_transparent = transparent + data.st.set_material(mat) + data.st.add_color(Color(0,1,1)) + var cmf = [] + for v in range(0,4): + data.st.add_uv(core.default_node.uv[v]) + data.st.add_vertex(core.default_node.faces[f][v]+lpos) + cmf.push_back(core.default_node.faces[f][v]+lpos) + + data.st.commit(data.mesh) + # the faces is added, now add to the collision + # the TRIANGLE_FAN allows us to be more flexible models, but the trimesh do not work with it + # so we are using TRIANGLES for that + if reg.get("collidable") != false: + data.cst.begin(Mesh.PRIMITIVE_TRIANGLES) + data.cst.add_triangle_fan(cmf) + data.cst.commit(data.collision_mesh) + data.st.clear() + data.cst.clear() + chunk_mesh.mesh = data.mesh + chunk_mesh.get_node_or_null("body/collision").shape = data.collision_mesh.create_trimesh_shape() + chunks_in_progress.erase(di) + progress2del[di] = di + # the chunk is done, now work on next update +func update(pos): + if get_chunk_at_pos(pos) == null: + new_chunk(pos) + #no chunk here, generate it quickly + core.current_mapgen.call_func(to_chunk_pos(pos)) + return + + var chunkid = pos_to_chunkid(pos) + var data = { + vertex = {}, + full_cubes = core.settings.full_3d_cubes, + mesh = Mesh.new(), + collision_mesh = Mesh.new(), + chunkid = chunkid, + chunk_pos = get_chunk(chunkid).transform.origin, + st = SurfaceTool.new(), + cst = SurfaceTool.new(), + range_x = {a=-core.chunk_size/2,b=core.chunk_size/2}, + range_y = {a=-core.chunk_size/2,b=core.chunk_size/2}, + range_z = {a=-core.chunk_size/2,b=core.chunk_size/2}, + } + chunks_in_progress[chunkid] = data diff --git a/chunk.tscn b/chunk.tscn new file mode 100644 index 0000000..37fd509 --- /dev/null +++ b/chunk.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://chunk.gd" type="Script" id=1] + +[node name="chunks" type="Spatial"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, 0.5, -0.5 ) +script = ExtResource( 1 ) diff --git a/core.gd b/core.gd new file mode 100644 index 0000000..03f936f --- /dev/null +++ b/core.gd @@ -0,0 +1,125 @@ +extends Node + +var chunk #noderef functions +var chunks = {} #contains all chucks, using Vector3() as keys or "id" +var chunk_size=8#16 are more common for this kind of game, but is 4X slower to update + +var default_texture = load("res://res/stone.png")#used if we are unable to get the nodes tiles +var player = {name="singleplayer",object=null,inventory=["stone","dirt","grassy","water_source"],inventory_index=0} +var map = {}#contains all nodes, using Vector3() as keys or "id", contains a number/node id, strings would use too much memory +var collision_map = {} +var settings = { + full_3d_cubes=false, + update_chunk_rules=[Vector3(-1,0,0),Vector3(1,0,0),Vector3(0,0,-1),Vector3(0,0,1),Vector3(0,-1,0),Vector3(0,1,0)], + ganerate_chunk_range=4, + max_update_nodes=512, + } +var default_node_id = 7 +var mapgen = {} +var current_mapgen # funcref +var register = { + nodes = { + none={id=0,name="none",drawtype="none",tiles=[]}, + air={id=1,name="air",drawtype="none",tiles=[],collidable=false,solid_surface=false}, + stone={id=2,name="stone",drawtype="default",tiles=[load("res://res/stone.png")]}, + grassy={id=3,name="grassy",drawtype="default",tiles=[ + load("res://res/grass.png"), + load("res://res/dirt.png"), + load("res://res/grass_dirt.png"), + load("res://res/grass_dirt.png"), + load("res://res/grass_dirt.png"), + load("res://res/grass_dirt.png"), + ]}, + dirt={id=4,name="dirt",drawtype="default",tiles=[load("res://res/dirt.png")]}, + water_source={id=5,name="water_source",replaceable=true,drawtype="liquid",collidable=false,transparent=true,solid_surface=false,tiles=[load("res://res/water.png")]}, + }, + id = {0:"none",1:"air",2:"stone",3:"grassy",4:"dirt",5:"water_source"}, +} +var default_node = { + uv = [Vector2(0,0),Vector2(0,1),Vector2(1,1),Vector2(1,0)], + dir = [Vector3(0,1,0),Vector3(0,-1,0),Vector3(1,0,0),Vector3(-1,0,0),Vector3(0,0,-1),Vector3(0,0,1)], + faces = [ + [Vector3(1,0,0),Vector3(1,0,1),Vector3(0,0,1),Vector3(0,0,0)], #up y+ + [Vector3(0,-1,0),Vector3(0,-1,1),Vector3(1,-1,1),Vector3(1,-1,0)], #down y- + [Vector3(1,0,0),Vector3(1,-1,0),Vector3(1,-1,1),Vector3(1,0,1)], #north x+ + [Vector3(0,0,1),Vector3(0,-1,1),Vector3(0,-1,0),Vector3(0,0,0)], #south x- + [Vector3(0,0,0),Vector3(0,-1,0),Vector3(1,-1,0),Vector3(1,0,0)], #east z+ + [Vector3(1,0,1),Vector3(1,-1,1),Vector3(0,-1,1),Vector3(0,0,1)], #west z- + ] +} + +#returns name of node you are pointing at, pos would be more usefull i think +#use the penultimate pos to get the node next to it +func pointed_at_node(): + var pos = player.object.get_translation() + var aim = player.object.get_node("head/Camera").get_global_transform().basis + var hpos = player.object.get_node("head").get_translation() + for i in range(-1,-500,-1): + var p = (pos + hpos+(aim.z*Vector3(i*0.01,i*0.01,i*0.01)))#.round() + var rp = p.round() + var id = map.get(rp) + var reg = get_node_reg(id) + if reg != null and reg.get("drawtype") != "none" and reg.get("collidable") != false: + if (p.x >= rp.x-0.5 and p.x <= rp.x+0.5) and (p.y >= rp.y-0.5 and p.y <= rp.y+0.5) and (p.z >= rp.z-0.5 and p.z <= rp.z+0.5): + return reg.name + return "none" + + +#problity you finds a better way to use this +#but this is what i used while testing +func pointed_node_action(n): + var pos = player.object.get_translation() + var aim = player.object.get_node("head/Camera").get_global_transform().basis + var hpos = player.object.get_node("head").get_translation() + var lpos = (pos + hpos+aim.z).round() + + for i in range(-1,-500,-1): + var p = (pos + hpos+(aim.z*Vector3(i*0.01,i*0.01,i*0.01)))#.round() + var rp = p.round() + var id = map.get(rp) + + + if id and id != 1: + if core.chunk.get_chunk_at_pos(rp): + if (p.x >= rp.x-0.5 and p.x <= rp.x+0.5) and (p.y >= rp.y-0.5 and p.y <= rp.y+0.5) and (p.z >= rp.z-0.5 and p.z <= rp.z+0.5): + var node = player.inventory[player.inventory_index] if n == 0 else "air" + var pp = rp + if n == 0: + var Name = register.id[id] + var reg = register.nodes[Name] + pp = rp if reg.get("replaceable") == true else lpos + set_node({name=node,pos=pp}) + return + lpos = rp + +func get_node_reg(v):#a flexible way to get node properties by pos, id or name + if v is Vector3: + v = v.round() + v = map.get(v) + elif v is String: + return register.nodes.get(v) + var n = register.id.get(v) + return register.nodes.get(n) + +func get_node(pos):#returns node id + assert(typeof(pos) == TYPE_VECTOR3,"ERROR: set_node: pos required!") + return map.get(pos) + +func set_node(def:Dictionary):# set node + assert(typeof(def.get("pos")) == TYPE_VECTOR3 and typeof(def.get("name")) == TYPE_STRING,"ERROR: set_node: def.pos & def.name required!") + var n = register.nodes.get(def.name) + assert(n != null,str('ERROR: set_node: "',def.name,'"', " doesn't exists")) + var rpos = def.pos.round() + map[rpos] = get_node_reg(def.name).id + +#check if chunks around the node need to be updated + var cid = chunk.pos_to_chunkid(rpos) + for r in settings.update_chunk_rules.size(): + var near_chunk = rpos+settings.update_chunk_rules[r] + if chunk.pos_to_chunkid(near_chunk) != cid: + chunk.update(near_chunk) +#check the chunk + chunk.update(rpos) + +func inset_map_node_id(id,pos):# easyer to use + map[pos] = id diff --git a/default_env.tres b/default_env.tres new file mode 100644 index 0000000..20207a4 --- /dev/null +++ b/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/main.tscn b/main.tscn new file mode 100644 index 0000000..bae8581 --- /dev/null +++ b/main.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://player.tscn" type="PackedScene" id=1] +[ext_resource path="res://chunk.tscn" type="PackedScene" id=2] + +[sub_resource type="Environment" id=1] +background_mode = 1 +background_color = Color( 0.447059, 0.666667, 0.858824, 1 ) +ambient_light_color = Color( 1, 1, 1, 1 ) + +[node name="main" type="Spatial"] + +[node name="chunks" parent="." instance=ExtResource( 2 )] + +[node name="player" parent="." instance=ExtResource( 1 )] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0 ) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource( 1 ) diff --git a/mapgen.gd b/mapgen.gd new file mode 100644 index 0000000..3141c56 --- /dev/null +++ b/mapgen.gd @@ -0,0 +1,72 @@ +extends Node + +var timer = 1 + +func _ready(): + core.current_mapgen = funcref(self,"super_flatland") + yield(get_tree().create_timer(2),"timeout") + for x in range(-4,4): + for z in range(-4,4): + core.inset_map_node_id(5,Vector3(x,0,z)) + core.chunk.update(Vector3(0,0,0)) + +var n2gc_timer = -0.01 +var n2gc_time = 0 +func _process(delta): + timer += delta + if timer > n2gc_time: + if n2gc_timer >= 1: + n2gc_timer = 0 + n2gc_time = 1 + else: + n2gc_timer += timer + timer = 0 + + var ppos = core.player.object.global_transform.origin + + var pos = core.chunk.to_chunk_pos(ppos) + if core.chunk.get_chunk_at_pos(pos) == null: + core.chunk.new_chunk(pos) + core.current_mapgen.call_func(pos) + n2gc_time = 0 + n2gc_timer = 0 + #return + for i in range(1,core.settings.ganerate_chunk_range): + var r = core.chunk_size*i + var s = core.chunk_size + for x in range(-r,r,s): + for y in range(-r,r,s): + for z in range(-r,r,s): + pos = Vector3(x,y,z) + core.chunk.to_chunk_pos(ppos) + if core.chunk.get_chunk_at_pos(pos) == null: + core.chunk.new_chunk(pos) + core.current_mapgen.call_func(pos) + n2gc_time = 0 + n2gc_timer = 0 + +#generates a flat map: +#all nodes above 9 will be air +#0 = grassy +#-1 - -3 = dirt +#-4 and lower = stone +func super_flatland(pos): + var id + var grassy = core.get_node_reg("grassy").id + var dirt = core.get_node_reg("dirt").id + var stone = core.get_node_reg("stone").id + var air = core.get_node_reg("air").id + var Y + for x in range(-core.chunk_size/2,core.chunk_size/2): + for y in range(-core.chunk_size/2,core.chunk_size/2): + for z in range(-core.chunk_size/2,core.chunk_size/2): + Y = pos.y+y + if Y == 0: + id = grassy + elif Y < -3: + id = stone + elif Y < 0: + id = dirt + else: + id = air + core.inset_map_node_id(id,Vector3(x,y,z)+pos) + core.chunk.update(pos) diff --git a/player.gd b/player.gd new file mode 100644 index 0000000..7f0e0c2 --- /dev/null +++ b/player.gd @@ -0,0 +1,94 @@ +extends KinematicBody + +var direction = Vector3() +var velocity = Vector3() +var gravity = -27 +var jump_height = 10 +var walk_speed = 10 +var fpv_camera_angle = 0 +var fpv_mouse_sensitivity = 0.3 +var fly_mode = false + +func _ready(): + core.player.object = self + +#camera +func _input(event): + if Input.is_action_just_pressed("ui_cancel"): + get_tree().quit() + if event is InputEventMouseMotion: + rotate_y(deg2rad(-event.relative.x * fpv_mouse_sensitivity)) + var change = -event.relative.y * fpv_mouse_sensitivity + if change + fpv_camera_angle < 90 and change + fpv_camera_angle > -90: + $head/Camera.rotate_x(deg2rad(change)) + fpv_camera_angle += change + elif event is InputEventMouseButton: + if Input.is_action_just_pressed("LMB"): + core.pointed_node_action(0) + elif Input.is_action_just_pressed("RMB"): + core.pointed_node_action(1) + elif Input.is_action_just_pressed("WHEEL_UP"): + core.player.inventory_index += 1 + if core.player.inventory_index >= core.player.inventory.size(): + core.player.inventory_index = 0 + elif Input.is_action_just_pressed("WHEEL_DOWN"): + core.player.inventory_index -= 1 + if core.player.inventory_index <= 0: + core.player.inventory_index = core.player.inventory.size()-1 +# moving +func _process(delta): + direction = Vector3() + var aim = $head/Camera.get_global_transform().basis + var pos = transform.origin + var con = Vector3() + if Input.is_key_pressed(KEY_W): + con -= aim.z + if Input.is_key_pressed(KEY_S): + con += aim.z + if Input.is_key_pressed(KEY_A): + con -= aim.x + if Input.is_key_pressed(KEY_D): + con += aim.x + if Input.is_action_just_pressed("fly_mode"): + fly_mode = fly_mode == false + $Collision.disabled = fly_mode + velocity = Vector3(0,0,0) +#this lines just updates the screen info +#if you are not trying to solve a problem, this 4 lines is kinda useless, and useing unnecessarily performance + ui.screeninfo("player_pos",transform.origin) + ui.screeninfo("chunk_id",core.chunk.pos_to_chunkid(transform.origin)) + ui.screeninfo("chunk_pos",core.chunk.to_chunk_pos(transform.origin)) + ui.screeninfo("pointing_at",core.pointed_at_node()) + + + if fly_mode: + if Input.is_key_pressed(KEY_E): + con.y += 1 + if Input.is_key_pressed(KEY_Q): + con.y -= 1 + if Input.is_key_pressed(KEY_SHIFT): + con*=0.1 + transform.origin += con*0.2 + else: + var on_floor = is_on_floor() + direction = con + direction = direction.normalized() + if on_floor: + velocity.y = 0 + else: + #if player is inside a collidable block, freeze the movement to prevent falling through the ground + var id = core.map.get(pos.round()) + var n = core.register.id.get(id) if id != null else "default" + var reg = core.register.nodes.get(n) + if reg.get("collidable") != false: + velocity.y = 0 + return + velocity.y += gravity * delta + var tv = velocity + tv = velocity.linear_interpolate(direction * walk_speed,15 * delta) + velocity.x = tv.x + velocity.z = tv.z + velocity = move_and_slide(velocity,Vector3(0,1,0)) + # == jumping + if on_floor and Input.is_key_pressed(KEY_SPACE): + velocity.y = jump_height diff --git a/player.tscn b/player.tscn new file mode 100644 index 0000000..944b838 --- /dev/null +++ b/player.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://player.gd" type="Script" id=1] + +[sub_resource type="CubeMesh" id=1] + +[sub_resource type="SpatialMaterial" id=2] +albedo_color = Color( 1, 0, 0, 1 ) + +[sub_resource type="BoxShape" id=3] + +[node name="player" type="KinematicBody"] +script = ExtResource( 1 ) + +[node name="mesh" type="MeshInstance" parent="."] +transform = Transform( 0.4, 0, 0, 0, 1, 0, 0, 0, 0.4, 0, 0, 0 ) +mesh = SubResource( 1 ) +material/0 = SubResource( 2 ) + +[node name="Collision" type="CollisionShape" parent="."] +transform = Transform( 0.4, 0, 0, 0, 1, 0, 0, 0, 0.4, 0, 0, 0 ) +shape = SubResource( 3 ) + +[node name="head" type="Spatial" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8, 0 ) + +[node name="Camera" type="Camera" parent="head"] diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..a84f6a8 --- /dev/null +++ b/project.godot @@ -0,0 +1,84 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +[application] + +config/name="Voxel Prototype" +run/main_scene="res://main.tscn" +config/icon="res://icon.png" + +[autoload] + +core="*res://core.gd" +mapgen="*res://mapgen.gd" +ui="*res://ui.tscn" + +[display] + +window/stretch/mode="viewport" + +[importer_defaults] + +texture={ +"compress/bptc_ldr": 0, +"compress/hdr_mode": 0, +"compress/lossy_quality": 0.7, +"compress/mode": 2, +"compress/normal_map": 0, +"detect_3d": false, +"flags/anisotropic": false, +"flags/filter": false, +"flags/mipmaps": true, +"flags/repeat": true, +"flags/srgb": 1, +"process/HDR_as_SRGB": false, +"process/fix_alpha_border": false, +"process/invert_color": false, +"process/premult_alpha": false, +"size_limit": 0, +"stream": false, +"svg/scale": 1.0 +} + +[input] + +fly_mode={ +"deadzone": 0.5, +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":70,"unicode":0,"echo":false,"script":null) + ] +} +LMB={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) + ] +} +RMB={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":2,"pressed":false,"doubleclick":false,"script":null) + ] +} +WHEEL_UP={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":4,"pressed":false,"doubleclick":false,"script":null) + ] +} +WHEEL_DOWN={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":5,"pressed":false,"doubleclick":false,"script":null) + ] +} + +[physics] + +common/enable_pause_aware_picking=true + +[rendering] + +environment/default_environment="res://default_env.tres" diff --git a/res/crosshair.png b/res/crosshair.png new file mode 100644 index 0000000..3fe3b27 Binary files /dev/null and b/res/crosshair.png differ diff --git a/res/dirt.png b/res/dirt.png new file mode 100644 index 0000000..9c46f6e Binary files /dev/null and b/res/dirt.png differ diff --git a/res/grass.png b/res/grass.png new file mode 100644 index 0000000..ad1d09a Binary files /dev/null and b/res/grass.png differ diff --git a/res/grass_dirt.png b/res/grass_dirt.png new file mode 100644 index 0000000..ddc7e7c Binary files /dev/null and b/res/grass_dirt.png differ diff --git a/res/stone.png b/res/stone.png new file mode 100644 index 0000000..add1d94 Binary files /dev/null and b/res/stone.png differ diff --git a/res/water.png b/res/water.png new file mode 100644 index 0000000..9d3cb39 Binary files /dev/null and b/res/water.png differ diff --git a/screenshot.PNG b/screenshot.PNG new file mode 100644 index 0000000..5d4995f Binary files /dev/null and b/screenshot.PNG differ diff --git a/ui.gd b/ui.gd new file mode 100644 index 0000000..a8e4bf8 --- /dev/null +++ b/ui.gd @@ -0,0 +1,29 @@ +extends Control + +var _screeninfo = { + player_pos = Vector3(), + chunk_id = Vector3(), + chunk_pos = Vector3(), + pointing_at = "", +} + +func _ready(): + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + + var ss = get_viewport_rect().size/2 + var cs = $crosshair.rect_size / 2 + $crosshair.rect_position = ss - cs + + var p = OS.get_screen_size()/2 + var s = OS.window_size/2 + var winpos = p-s + winpos.y = 0 #now we can see the output + OS.set_window_position(winpos) + +#if you are not trying to solve a problem, this one is kinda useless +func screeninfo(lab,v): + _screeninfo[lab] = v + var s = _screeninfo.player_pos.round() + var c = _screeninfo.chunk_id + var p = _screeninfo.chunk_pos + $screeninfo.text = str("Pos: ",s.x,",",s.y,",",s.z," Chunk ID: ",c.x,",",c.y,",",c.z," Chunk pos: ",p.x,",",p.y,",",p.z," Pointing at: ",_screeninfo.pointing_at) diff --git a/ui.tscn b/ui.tscn new file mode 100644 index 0000000..25ae4ff --- /dev/null +++ b/ui.tscn @@ -0,0 +1,30 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://ui.gd" type="Script" id=1] +[ext_resource path="res://res/crosshair.png" type="Texture" id=2] + +[node name="ui" type="Control"] +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="crosshair" type="TextureRect" parent="."] +margin_left = 60.1041 +margin_top = 207.182 +margin_right = 80.1041 +margin_bottom = 227.182 +texture = ExtResource( 2 ) +expand = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="screeninfo" type="Label" parent="."] +margin_right = 108.0 +margin_bottom = 15.0 +rect_scale = Vector2( 2, 2 ) +text = "Pos:, Chunk ID:, Pointing at:" +__meta__ = { +"_edit_use_anchors_": false +}