first commit
This commit is contained in:
113
scripts/world.gd
Normal file
113
scripts/world.gd
Normal file
@@ -0,0 +1,113 @@
|
||||
extends Node3D
|
||||
## Gelaende, Vegetation und Umgebung. Baeume laufen ueber MultiMesh,
|
||||
## damit auch mehrere hundert Stueck guenstig bleiben.
|
||||
|
||||
const Mat = preload("res://scripts/mat.gd")
|
||||
const Deco = preload("res://scripts/deco.gd")
|
||||
|
||||
const GRASS := Color("7cb85a")
|
||||
const GRASS_DARK := Color("74b054")
|
||||
const WATER := Color("4f9fd6")
|
||||
const SAND := Color("e0c98a")
|
||||
const EXTENT := 360.0
|
||||
|
||||
var _rng: RandomNumberGenerator
|
||||
|
||||
func build(rng: RandomNumberGenerator, track, stations: Array) -> void:
|
||||
_rng = rng
|
||||
_ground()
|
||||
_scatter(track, stations)
|
||||
|
||||
func _flat_disc(pos: Vector3, radius: float, color: Color, height := 0.06) -> void:
|
||||
var m := MeshInstance3D.new()
|
||||
m.mesh = Deco.cyl(radius, height, 24)
|
||||
m.material_override = Mat.flat(color)
|
||||
m.position = pos
|
||||
add_child(m)
|
||||
|
||||
func _ground() -> void:
|
||||
var plane := PlaneMesh.new()
|
||||
plane.size = Vector2(1000, 1000)
|
||||
var g := MeshInstance3D.new()
|
||||
g.mesh = plane
|
||||
g.material_override = Mat.flat(GRASS)
|
||||
add_child(g)
|
||||
|
||||
_flat_disc(Vector3(-230, 0.02, 150), 72.0, SAND, 0.05)
|
||||
_flat_disc(Vector3(-230, 0.04, 150), 60.0, WATER, 0.05)
|
||||
for i in 18:
|
||||
var p := Vector2(_rng.randf_range(-EXTENT, EXTENT), _rng.randf_range(-EXTENT, EXTENT))
|
||||
_flat_disc(Vector3(p.x, 0.01, p.y), _rng.randf_range(18.0, 44.0), GRASS_DARK, 0.03)
|
||||
|
||||
func _multi(mesh: Mesh, items: Array) -> void:
|
||||
if items.is_empty():
|
||||
return
|
||||
var mm := MultiMesh.new()
|
||||
mm.transform_format = MultiMesh.TRANSFORM_3D
|
||||
mm.use_colors = true
|
||||
mm.mesh = mesh
|
||||
mm.instance_count = items.size()
|
||||
for i in items.size():
|
||||
var it: Dictionary = items[i]
|
||||
mm.set_instance_transform(i, it["xf"])
|
||||
# Instanzfarben gehen roh in den Shader, deshalb hier nach Linear wandeln.
|
||||
mm.set_instance_color(i, (it["color"] as Color).srgb_to_linear())
|
||||
var mmi := MultiMeshInstance3D.new()
|
||||
mmi.multimesh = mm
|
||||
mmi.material_override = Mat.flat(Color.WHITE)
|
||||
add_child(mmi)
|
||||
|
||||
func _scatter(track, stations: Array) -> void:
|
||||
var trunks: Array = []
|
||||
var cones: Array = []
|
||||
var blobs: Array = []
|
||||
var rocks: Array = []
|
||||
|
||||
var placed := 0
|
||||
var tries := 0
|
||||
while placed < 620 and tries < 12000:
|
||||
tries += 1
|
||||
var p := Vector2(_rng.randf_range(-EXTENT, EXTENT), _rng.randf_range(-EXTENT, EXTENT))
|
||||
var closest: Vector3 = track.path.curve.get_closest_point(Vector3(p.x, 0, p.y))
|
||||
if Vector2(closest.x, closest.z).distance_to(p) < 11.0:
|
||||
continue
|
||||
if p.distance_to(Vector2(-230, 150)) < 78.0:
|
||||
continue
|
||||
var blocked := false
|
||||
for st in stations:
|
||||
if p.distance_to(Vector2(st.global_position.x, st.global_position.z)) < 30.0:
|
||||
blocked = true
|
||||
break
|
||||
if blocked:
|
||||
continue
|
||||
placed += 1
|
||||
var yaw := _rng.randf() * TAU
|
||||
if _rng.randf() < 0.6:
|
||||
var h := _rng.randf_range(4.0, 8.5)
|
||||
var col: Color = Deco.PINE[_rng.randi() % Deco.PINE.size()]
|
||||
trunks.append(_item(p, h * 0.16, Vector3(1, h * 0.3, 1), yaw, Deco.TRUNK))
|
||||
var tiers := 3 if h > 6.0 else 2
|
||||
for i in tiers:
|
||||
var f := float(i) / float(tiers)
|
||||
var r := lerpf(h * 0.3, h * 0.14, f)
|
||||
var th := h * 0.44
|
||||
var y := h * 0.26 + f * h * 0.32 + th * 0.5
|
||||
cones.append(_item(p, y, Vector3(r, th, r), yaw, col))
|
||||
elif _rng.randf() < 0.85:
|
||||
var h := _rng.randf_range(3.2, 6.0)
|
||||
var col: Color = Deco.LEAF[_rng.randi() % Deco.LEAF.size()]
|
||||
trunks.append(_item(p, h * 0.28, Vector3(0.9, h * 0.55, 0.9), yaw, Deco.TRUNK))
|
||||
var r := h * 0.44
|
||||
blobs.append(_item(p, h * 0.55 + r * 0.5, Vector3(r, r, r), yaw, col))
|
||||
else:
|
||||
var r := _rng.randf_range(0.7, 2.0)
|
||||
rocks.append(_item(p, r * 0.35, Vector3(r, r * 0.55, r * 1.1), yaw, Deco.ROCK))
|
||||
|
||||
_multi(Deco.cyl(0.18, 1.0, 6), trunks)
|
||||
_multi(Deco.cone(1.0, 1.0, 7), cones)
|
||||
_multi(Deco.blob(1.0), blobs)
|
||||
_multi(Deco.blob(1.0), rocks)
|
||||
|
||||
func _item(p: Vector2, y: float, scale: Vector3, yaw: float, color: Color) -> Dictionary:
|
||||
var b := Basis(Vector3.UP, yaw).scaled(scale)
|
||||
return {"xf": Transform3D(b, Vector3(p.x, y, p.y)), "color": color}
|
||||
Reference in New Issue
Block a user