Jonas Reith fa38e603a1 Initial commit: WayfarersWanderer project state
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
2026-08-26 19:05:30 +02:00

135 lines
4.9 KiB
GDScript

extends Node3D
const W := 10 # Breite X
const D := 10 # Tiefe Z
const H := 3 # Höhe Y
# Fluss läuft entlang Z, mittig auf X
const FLUSS_X := 5 # Welche X-Spalte (0-basiert, Mitte = 4 oder 5)
const FLUSS_TIEFE := 2 # Wie viele Blöcke von oben rausgenommen
const WASSER_Y := 0 # Y-Index wo Wasser sitzt (unterster Block des Grabens)
# Materialien — einmal erstellen, mehrfach nutzen
var mat_erde : StandardMaterial3D
var mat_gras : StandardMaterial3D
var mat_wasser : ShaderMaterial
func _ready() -> void:
_make_materials()
_build()
# ═══════════════════════════════════════════════
# MATERIALIEN
# ═══════════════════════════════════════════════
func _make_materials() -> void:
mat_erde = StandardMaterial3D.new()
mat_erde.albedo_color = Color(0.38, 0.26, 0.16)
mat_erde.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
mat_gras = StandardMaterial3D.new()
mat_gras.albedo_color = Color(0.35, 0.60, 0.22)
mat_gras.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
# Wasser-Shader
var shader := Shader.new()
shader.code = """
shader_type spatial;
render_mode unshaded, cull_disabled, blend_mix;
uniform vec4 color_shallow : source_color = vec4(0.2, 0.55, 0.85, 0.75);
uniform vec4 color_deep : source_color = vec4(0.1, 0.35, 0.70, 0.90);
uniform float speed : hint_range(0.0, 2.0) = 0.6;
uniform float wave_scale : hint_range(0.1, 5.0) = 1.5;
void fragment() {
vec2 uv = UV * wave_scale + vec2(TIME * speed, TIME * speed * 0.4);
float wave = sin(uv.x * 6.28) * 0.5 + 0.5;
wave += sin(uv.y * 6.28 * 1.3 + TIME * speed) * 0.3;
wave = clamp(wave * 0.5, 0.0, 1.0);
ALBEDO = mix(color_shallow.rgb, color_deep.rgb, wave);
ALPHA = mix(color_shallow.a, color_deep.a, wave);
}
"""
mat_wasser = ShaderMaterial.new()
mat_wasser.shader = shader
# ═══════════════════════════════════════════════
# WELT BAUEN
# ═══════════════════════════════════════════════
func _build() -> void:
for x in range(W):
for z in range(D):
_build_spalte(x, z)
func _build_spalte(x: int, z: int) -> void:
var ist_fluss := (x == FLUSS_X)
for y in range(H):
# Fluss-Graben: oberste FLUSS_TIEFE Blöcke fehlen
if ist_fluss and y >= (H - FLUSS_TIEFE):
continue
var mat : StandardMaterial3D
if y == H - 1 and not ist_fluss:
mat = mat_gras # Oberste Schicht = Gras
else:
mat = mat_erde # Alles darunter = Erde
_place_block(Vector3(x, y, z), mat)
# Wasser in den Graben
if ist_fluss:
var wasser_y := H - FLUSS_TIEFE # Wasser sitzt auf dem Boden des Grabens
_place_wasser(Vector3(x, wasser_y, z))
# Wasserfall: wo Fluss auf Z-Rand trifft
if ist_fluss and (z == 0 or z == D - 1):
_spawn_wasserfall(x, z)
# ═══════════════════════════════════════════════
# BLÖCKE PLATZIEREN
# ═══════════════════════════════════════════════
func _place_block(pos: Vector3, mat: StandardMaterial3D) -> void:
var mi := MeshInstance3D.new()
var box := BoxMesh.new()
box.size = Vector3(1, 1, 1)
box.surface_set_material(0, mat)
mi.mesh = box
mi.position = pos + Vector3(0.5, 0.5, 0.5) # Pivot unten-links
add_child(mi)
func _place_wasser(pos: Vector3) -> void:
var mi := MeshInstance3D.new()
var box := BoxMesh.new()
# Wasser etwas flacher als 1m damit man Tiefe sieht
box.size = Vector3(1.0, 0.65, 1.0)
box.surface_set_material(0, mat_wasser)
mi.mesh = box
mi.position = pos + Vector3(0.5, 0.33, 0.5)
mi.transparency = 0.3
add_child(mi)
# ═══════════════════════════════════════════════
# WASSERFALL
# ═══════════════════════════════════════════════
func _spawn_wasserfall(x: int, z: int) -> void:
# Vertikale Wasser-Plane von Graben-Unterkante bis Boden
var fall_h := float(H - FLUSS_TIEFE) # Höhe des Falls
var mi := MeshInstance3D.new()
var quad := QuadMesh.new()
quad.size = Vector2(1.0, fall_h)
quad.surface_set_material(0, mat_wasser)
mi.mesh = quad
# Positionierung: Außenkante der Platte
var dir_z := -1.0 if z == 0 else 1.0
mi.position = Vector3(
x + 0.5,
fall_h * 0.5, # Vertikal zentriert
z + 0.5 * dir_z # Außenkante
)
# Plane zeigt nach außen
mi.rotation.y = 0.0 if z == D - 1 else PI
add_child(mi)