Godot 4.6 exploration game with player movement, step-rotation camera rig, and POI interaction system (explore/rest/close menu). main.tscn is a test scene with placeholder props; debug/ holds unwired terrain prototypes (voxel river, procedural island mesh, cross-shaped hub
101 lines
3.1 KiB
GDScript
101 lines
3.1 KiB
GDScript
extends Node3D
|
|
|
|
@export var radius : float = 1024.0
|
|
@export var segments: int = 128
|
|
@export var seed_val: int = 42
|
|
@export var erosion : float = 0.18
|
|
|
|
func _ready() -> void:
|
|
_build()
|
|
|
|
func _build() -> void:
|
|
var noise := FastNoiseLite.new()
|
|
noise.seed = seed_val
|
|
noise.noise_type = FastNoiseLite.TYPE_SIMPLEX_SMOOTH
|
|
noise.frequency = 0.008
|
|
|
|
var st := SurfaceTool.new()
|
|
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
var verts: PackedVector3Array = []
|
|
var colrs: PackedColorArray = []
|
|
var seg := segments
|
|
|
|
for i in range(seg + 1):
|
|
for j in range(seg + 1):
|
|
var u := float(i) / seg
|
|
var v := float(j) / seg
|
|
var angle := u * TAU
|
|
var r := v * radius
|
|
var en := 1.0 + noise.get_noise_2d(
|
|
cos(angle) * 80.0,
|
|
sin(angle) * 80.0) * erosion
|
|
var x := cos(angle) * r * en
|
|
var z := sin(angle) * r * en
|
|
var dn := r / radius
|
|
# Komplett flach — nur Rand fällt ab
|
|
var y := -6.0 * pow(dn, 6.0)
|
|
verts.append(Vector3(x, y, z))
|
|
colrs.append(_col(dn))
|
|
|
|
for i in range(seg):
|
|
for j in range(seg):
|
|
var idx := i * (seg + 1) + j
|
|
var a := idx; var b := idx + 1
|
|
var c := idx+(seg+1); var d := idx+(seg+1)+1
|
|
var n := (verts[b]-verts[a]).cross(verts[c]-verts[a]).normalized()
|
|
for vtx in [a, b, c]:
|
|
st.set_normal(n); st.set_color(colrs[vtx])
|
|
st.add_vertex(verts[vtx])
|
|
for vtx in [b, d, c]:
|
|
st.set_normal(n); st.set_color(colrs[vtx])
|
|
st.add_vertex(verts[vtx])
|
|
|
|
var mesh := st.commit()
|
|
var mat := StandardMaterial3D.new()
|
|
mat.vertex_color_use_as_albedo = true
|
|
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
|
mesh.surface_set_material(0, mat)
|
|
var mi := MeshInstance3D.new()
|
|
mi.mesh = mesh
|
|
add_child(mi)
|
|
|
|
_build_underside()
|
|
|
|
func _col(dn: float) -> Color:
|
|
if dn > 0.93: return Color(0.45, 0.38, 0.28) # Erdrand
|
|
if dn > 0.85: return Color(0.38, 0.55, 0.25) # Gras außen
|
|
return Color(0.42, 0.65, 0.30) # Gras
|
|
|
|
func _build_underside() -> void:
|
|
var st := SurfaceTool.new()
|
|
st.begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
var seg := 80
|
|
var bot := Vector3(0, -18.0, 0)
|
|
var noise := FastNoiseLite.new()
|
|
noise.seed = seed_val + 1
|
|
for i in range(seg):
|
|
var a0 := float(i) / seg * TAU
|
|
var a1 := float(i+1) / seg * TAU
|
|
var r := radius * 0.9
|
|
var e0 := 1.0 + noise.get_noise_2d(cos(a0)*80, sin(a0)*80) * erosion
|
|
var e1 := 1.0 + noise.get_noise_2d(cos(a1)*80, sin(a1)*80) * erosion
|
|
var p0 := Vector3(cos(a0)*r*e0, -2.0, sin(a0)*r*e0)
|
|
var p1 := Vector3(cos(a1)*r*e1, -2.0, sin(a1)*r*e1)
|
|
var col := Color(0.30, 0.25, 0.18)
|
|
st.set_color(col); st.set_normal(Vector3(0,-1,0))
|
|
st.add_vertex(bot); st.add_vertex(p1); st.add_vertex(p0)
|
|
# Seite
|
|
var t0 := Vector3(p0.x, 0.0, p0.z)
|
|
var t1 := Vector3(p1.x, 0.0, p1.z)
|
|
st.add_vertex(p0); st.add_vertex(t0); st.add_vertex(p1)
|
|
st.add_vertex(t0); st.add_vertex(t1); st.add_vertex(p1)
|
|
var mesh := st.commit()
|
|
var mat := StandardMaterial3D.new()
|
|
mat.vertex_color_use_as_albedo = true
|
|
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
|
mat.cull_mode = BaseMaterial3D.CULL_DISABLED
|
|
mesh.surface_set_material(0, mat)
|
|
var mi := MeshInstance3D.new()
|
|
mi.mesh = mesh
|
|
add_child(mi)
|