update
This commit is contained in:
@@ -1,24 +1,21 @@
|
||||
extends Node3D
|
||||
class_name DreamWorld
|
||||
## Die Traumwelt: Insel mit drei betretbaren Gebäuden und dem Tor zur Erde.
|
||||
## Die Traumwelt: eine schwebende Insel mit einem Dorf. Vier Wesen wohnen hier,
|
||||
## jedes in seinem Haus, jedes mit eigenem Tagesablauf.
|
||||
|
||||
const INNEN_Y := -300.0
|
||||
var spawn := Vector3(0, 2.0, 20.0)
|
||||
var bewohner: Array = []
|
||||
|
||||
var spawn := Vector3(0, 2.0, 14.0)
|
||||
var _deko: Array = []
|
||||
var _regale: Dictionary = {} # tech_id -> MeshInstance3D
|
||||
var _stelen: Dictionary = {} # human_id -> Dictionary
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_environment()
|
||||
_insel()
|
||||
_gebaeude_bibliothek()
|
||||
_gebaeude_missionshalle()
|
||||
_gebaeude_meditation()
|
||||
_haeuser()
|
||||
_lichtung()
|
||||
_tor_zur_erde()
|
||||
Game.state_changed.connect(_refresh)
|
||||
_refresh()
|
||||
_wesen()
|
||||
|
||||
|
||||
func _environment() -> void:
|
||||
@@ -35,19 +32,19 @@ func _environment() -> void:
|
||||
sky.sky_material = mat
|
||||
env.sky = sky
|
||||
env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
|
||||
env.ambient_light_energy = 1.8
|
||||
env.ambient_light_energy = 2.1
|
||||
env.glow_enabled = true
|
||||
env.glow_intensity = 0.5
|
||||
env.glow_bloom = 0.15
|
||||
env.glow_intensity = 0.32
|
||||
env.glow_bloom = 0.05
|
||||
env.fog_enabled = true
|
||||
env.fog_light_color = Color(0.30, 0.18, 0.45)
|
||||
env.fog_density = 0.006
|
||||
env.fog_density = 0.0015
|
||||
we.environment = env
|
||||
add_child(we)
|
||||
|
||||
var sun := DirectionalLight3D.new()
|
||||
sun.rotation_degrees = Vector3(-46, 25, 0)
|
||||
sun.light_energy = 1.15
|
||||
sun.light_energy = 1.5
|
||||
sun.light_color = Color(0.85, 0.80, 1.0)
|
||||
sun.shadow_enabled = true
|
||||
sun.shadow_blur = 2.0
|
||||
@@ -55,24 +52,23 @@ func _environment() -> void:
|
||||
|
||||
|
||||
func _insel() -> void:
|
||||
Prims.cyl(self, Vector3(0, -1.0, 0), 50.0, 2.0, Color(0.28, 0.20, 0.42))
|
||||
Prims.cyl(self, Vector3(0, -4.0, 0), 38.0, 4.0, Color(0.20, 0.14, 0.32), false)
|
||||
Prims.cyl(self, Vector3(0, -9.0, 0), 20.0, 6.0, Color(0.15, 0.10, 0.26), false)
|
||||
# Wege
|
||||
var wege: Array[Vector3] = [Vector3(-22, 0, -6), Vector3(0, 0, -12), Vector3(22, 0, -6),
|
||||
Vector3(0, 0, 8)]
|
||||
for w in wege:
|
||||
var d: Vector3 = w.normalized() * (w.length() * 0.5)
|
||||
var b := Prims.box(self, Vector3(d.x, 0.02, d.z),
|
||||
Vector3(3.0, 0.08, w.length()), Color(0.45, 0.35, 0.62), false)
|
||||
b.rotation.y = atan2(w.x, w.z)
|
||||
Prims.cyl(self, Vector3(0, -1.03, 0), 52.0, 2.0, Color(0.48, 0.40, 0.64))
|
||||
Prims.cyl(self, Vector3(0, -4.0, 0), 40.0, 4.0, Color(0.34, 0.26, 0.50), false)
|
||||
Prims.cyl(self, Vector3(0, -9.0, 0), 22.0, 6.0, Color(0.24, 0.17, 0.38), false)
|
||||
|
||||
# Ringweg, auf dem die Wesen gehen
|
||||
for i in range(36):
|
||||
var a := TAU * float(i) / 36.0
|
||||
Prims.box(self, Vector3(cos(a) * 15.0, 0.03, sin(a) * 15.0),
|
||||
Vector3(2.6, 0.06, 2.6), Color(0.66, 0.58, 0.84), false)
|
||||
|
||||
# schwebende Deko
|
||||
var rng := RandomNumberGenerator.new()
|
||||
rng.seed = 7
|
||||
for i in range(34):
|
||||
var a := rng.randf() * TAU
|
||||
var r := rng.randf_range(16.0, 46.0)
|
||||
var p := Vector3(cos(a) * r, rng.randf_range(4.0, 22.0), sin(a) * r)
|
||||
var r := rng.randf_range(18.0, 48.0)
|
||||
var p := Vector3(cos(a) * r, rng.randf_range(5.0, 24.0), sin(a) * r)
|
||||
var s := rng.randf_range(0.6, 2.0)
|
||||
var c := Color(0.6 + rng.randf() * 0.3, 0.5 + rng.randf() * 0.4, 1.0)
|
||||
var wuerfel := Prims.box(self, p, Vector3(s, s, s), c, false, 1.1)
|
||||
@@ -80,175 +76,108 @@ func _insel() -> void:
|
||||
_deko.append(wuerfel)
|
||||
|
||||
|
||||
func _haeuser() -> void:
|
||||
for key in DreamDB.PLACES:
|
||||
var pl: Dictionary = DreamDB.PLACES[key]
|
||||
var s: Array = pl["size"]
|
||||
if s[0] <= 0.0:
|
||||
continue
|
||||
var c := Orte.center(DreamDB.PLACES, key)
|
||||
var groesse := Vector3(s[0], 3.2, s[1])
|
||||
var farbe: Color = pl["color"]
|
||||
Prims.room(self, c, groesse, farbe, farbe.darkened(0.35),
|
||||
Orte.DIR_VEC[pl["dir"]], 3.4, true)
|
||||
Prims.label(self, c + Vector3(0, 5.0, 0), pl["name"], 0.6, Color(1, 0.95, 0.85))
|
||||
_einrichtung(c, groesse, farbe, key)
|
||||
|
||||
var licht := OmniLight3D.new()
|
||||
licht.position = c + Vector3(0, 2.4, 0)
|
||||
licht.omni_range = 18.0
|
||||
licht.light_energy = 2.2
|
||||
licht.light_color = farbe.lightened(0.5)
|
||||
add_child(licht)
|
||||
|
||||
# Weg von der Tür zum Ring
|
||||
var tuer := Orte.door(DreamDB.PLACES, key)
|
||||
var weg := tuer.normalized() * 15.0 - tuer
|
||||
var b := Prims.box(self, (tuer + tuer.normalized() * 15.0) * 0.5 + Vector3(0, 0.03, 0),
|
||||
Vector3(2.4, 0.06, weg.length()), Color(0.66, 0.58, 0.84), false)
|
||||
b.rotation.y = atan2(weg.x, weg.z)
|
||||
|
||||
|
||||
func _einrichtung(c: Vector3, groesse: Vector3, farbe: Color, key: String) -> void:
|
||||
var w := groesse.x * 0.5 - 1.8
|
||||
var h := groesse.z * 0.5 - 1.8
|
||||
# Schlafnest hat jedes Haus
|
||||
Prims.cyl(self, c + Vector3(-w, 0.3, -h), 1.4, 0.5, farbe.darkened(0.2), false)
|
||||
match key:
|
||||
"haus_ailen": # Webstuhl
|
||||
Prims.box(self, c + Vector3(w, 1.1, 0), Vector3(0.3, 2.2, 3.0), farbe.darkened(0.45))
|
||||
for i in range(5):
|
||||
Prims.box(self, c + Vector3(w, 1.1, -1.2 + i * 0.6), Vector3(0.1, 1.8, 0.06),
|
||||
Color(0.9, 0.85, 1.0), false, 1.4)
|
||||
"haus_morr": # Regale voller Fundstücke
|
||||
for i in range(3):
|
||||
Prims.box(self, c + Vector3(w, 0.6 + i * 0.7, 0), Vector3(1.2, 0.12, 4.0),
|
||||
farbe.darkened(0.45))
|
||||
for j in range(4):
|
||||
Prims.box(self, c + Vector3(w, 0.85 + i * 0.7, -1.5 + j * 1.0),
|
||||
Vector3(0.4, 0.4, 0.4), Color(0.8, 0.9, 1.0), false, 0.8)
|
||||
"haus_ivo": # Karten und ein Fernrohr
|
||||
Prims.box(self, c + Vector3(w, 0.75, 0), Vector3(1.6, 0.12, 2.6), farbe.darkened(0.45))
|
||||
var rohr := Prims.cyl(self, c + Vector3(w, 1.6, 0), 0.18, 2.0,
|
||||
Color(0.85, 0.9, 1.0), false, 0.6)
|
||||
rohr.rotation.x = 0.9
|
||||
"haus_sela": # Schale mit Licht
|
||||
Prims.cyl(self, c + Vector3(w, 0.5, 0), 1.0, 1.0, farbe.darkened(0.4), false)
|
||||
Prims.sphere(self, c + Vector3(w, 1.4, 0), 0.55, Color(0.8, 1.0, 1.0), 2.0)
|
||||
|
||||
|
||||
func _lichtung() -> void:
|
||||
var c := Orte.center(DreamDB.PLACES, "lichtung")
|
||||
Prims.cyl(self, c + Vector3(0, 0.04, 0), 11.0, 0.12, Color(0.60, 0.52, 0.78), false)
|
||||
Prims.cyl(self, c + Vector3(0, 0.14, 0), 3.2, 0.2, Color(0.55, 0.80, 1.0, 0.5), false, 1.2)
|
||||
for i in range(8):
|
||||
var a := TAU * float(i) / 8.0
|
||||
var p := c + Vector3(cos(a) * 8.5, 0, sin(a) * 8.5)
|
||||
Prims.cyl(self, p + Vector3(0, 1.6, 0), 0.28, 3.2, Color(0.72, 0.64, 0.88))
|
||||
Prims.sphere(self, p + Vector3(0, 3.6, 0), 0.42, Color(0.75, 0.85, 1.0), 2.0)
|
||||
Prims.label(self, c + Vector3(0, 5.2, 0), DreamDB.PLACES["lichtung"]["name"], 0.6,
|
||||
Color(1, 0.95, 0.85))
|
||||
|
||||
|
||||
func _tor_zur_erde() -> void:
|
||||
var pos := Orte.center(DreamDB.PLACES, "tor")
|
||||
Prims.cyl(self, pos + Vector3(0, 0.3, 0), 5.5, 0.6, Color(0.35, 0.30, 0.50))
|
||||
for i in range(10):
|
||||
var a := PI * float(i) / 9.0
|
||||
Prims.box(self, pos + Vector3(cos(a) * 4.2, sin(a) * 4.2 + 0.6, 0),
|
||||
Vector3(0.7, 0.7, 0.7), Color(0.5, 0.85, 1.0), false, 1.8)
|
||||
var scheibe := Prims.cyl(self, pos + Vector3(0, 2.6, 0), 3.0, 0.2,
|
||||
Color(0.45, 0.75, 1.0, 0.28), false, 1.0)
|
||||
scheibe.rotation.x = PI * 0.5
|
||||
Prims.label(self, pos + Vector3(0, 6.4, 0), "Tor zur Erde", 0.8, Color(0.7, 0.95, 1))
|
||||
|
||||
var n := Node3D.new()
|
||||
n.position = pos + Vector3(0, 1.6, 0)
|
||||
add_child(n)
|
||||
n.add_to_group("interactable")
|
||||
n.set_meta("kind", "erde")
|
||||
n.set_meta("arg", "")
|
||||
n.set_meta("titel", "Tor zur Erde")
|
||||
|
||||
|
||||
func _wesen() -> void:
|
||||
for i in range(DreamDB.LIST.size()):
|
||||
var w := Bewohner.new()
|
||||
add_child(w)
|
||||
w.setup(DreamDB.LIST[i], i, DreamDB.PLACES)
|
||||
bewohner.append(w)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
for i in range(_deko.size()):
|
||||
var n: Node3D = _deko[i]
|
||||
n.rotation.y += delta * (0.2 + 0.05 * (i % 5))
|
||||
n.rotation.x += delta * 0.13
|
||||
n.position.y += sin(Time.get_ticks_msec() * 0.0007 + i) * delta * 0.6
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- Bausteine
|
||||
|
||||
## Erzeugt Außenbau + Innenraum und verbindet beide mit Tür-Zonen.
|
||||
func _gebaeude(titel: String, a_center: Vector3, a_size: Vector3,
|
||||
i_center: Vector3, i_size: Vector3, farbe: Color) -> Node3D:
|
||||
Prims.room(self, a_center, a_size, farbe, farbe.darkened(0.3), Vector3.BACK, 3.6, false)
|
||||
Prims.box(self, a_center + Vector3(0, a_size.y + 0.25, 0),
|
||||
Vector3(a_size.x + 1.0, 0.5, a_size.z + 1.0), farbe.lightened(0.15))
|
||||
Prims.box(self, a_center + Vector3(0, a_size.y + 1.1, 0),
|
||||
Vector3(a_size.x * 0.5, 1.2, a_size.z * 0.5), farbe.lightened(0.3))
|
||||
Prims.label(self, a_center + Vector3(0, a_size.y + 3.0, 0), titel, 1.4,
|
||||
Color(1, 0.95, 0.8))
|
||||
|
||||
var aussen_tuer := a_center + Vector3(0, 0, a_size.z * 0.5)
|
||||
var draussen := a_center + Vector3(0, 0.2, a_size.z * 0.5 + 3.2)
|
||||
|
||||
var innen := Node3D.new()
|
||||
innen.name = titel.replace(" ", "_")
|
||||
add_child(innen)
|
||||
Prims.room(innen, i_center, i_size, farbe.lightened(0.12), farbe.darkened(0.25),
|
||||
Vector3.BACK, 3.6, true)
|
||||
Prims.box(innen, i_center + Vector3(0, i_size.y + 0.2, 0),
|
||||
Vector3(i_size.x, 0.4, i_size.z), farbe.darkened(0.4))
|
||||
for sx: float in [-1.0, 1.0]:
|
||||
for sz: float in [-1.0, 1.0]:
|
||||
var l := OmniLight3D.new()
|
||||
l.position = i_center + Vector3(sx * i_size.x * 0.28, i_size.y - 0.8, sz * i_size.z * 0.28)
|
||||
l.omni_range = 34.0
|
||||
l.light_energy = 4.5
|
||||
l.light_color = Color(0.90, 0.90, 1.0)
|
||||
innen.add_child(l)
|
||||
|
||||
var innen_spawn := i_center + Vector3(0, 0.3, i_size.z * 0.5 - 3.0)
|
||||
_tuer(self, aussen_tuer + Vector3(0, 1.2, 0), innen_spawn)
|
||||
_tuer(innen, i_center + Vector3(0, 1.2, i_size.z * 0.5), draussen)
|
||||
Prims.label(innen, i_center + Vector3(0, i_size.y - 0.9, i_size.z * 0.5 - 0.35), "Ausgang", 0.45,
|
||||
Color(1, 0.85, 0.6))
|
||||
return innen
|
||||
|
||||
|
||||
func _tuer(parent: Node, pos: Vector3, ziel: Vector3) -> void:
|
||||
var a := Area3D.new()
|
||||
a.position = pos
|
||||
var cs := CollisionShape3D.new()
|
||||
var sh := BoxShape3D.new()
|
||||
sh.size = Vector3(3.4, 2.4, 1.6)
|
||||
cs.shape = sh
|
||||
a.add_child(cs)
|
||||
parent.add_child(a)
|
||||
a.body_entered.connect(func(body: Node3D) -> void:
|
||||
if body is Player and Game.teleport_lock <= 0.0:
|
||||
Game.teleport_lock = 0.9
|
||||
body.global_position = ziel
|
||||
body.velocity = Vector3.ZERO)
|
||||
|
||||
|
||||
func _interaktion(parent: Node, pos: Vector3, kind: String, arg: String, titel: String) -> Node3D:
|
||||
var n := Node3D.new()
|
||||
n.position = pos
|
||||
parent.add_child(n)
|
||||
n.add_to_group("interactable")
|
||||
n.set_meta("kind", kind)
|
||||
n.set_meta("arg", arg)
|
||||
n.set_meta("titel", titel)
|
||||
return n
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- Gebäude
|
||||
|
||||
func _gebaeude_bibliothek() -> void:
|
||||
var innen := _gebaeude("Bibliothek der Techniken",
|
||||
Vector3(-24, 0, -16), Vector3(16, 5, 14),
|
||||
Vector3(0, INNEN_Y, 0), Vector3(34, 6, 24),
|
||||
Color(0.58, 0.50, 0.80))
|
||||
Prims.label(innen, Vector3(0, INNEN_Y + 5.0, -10.5),
|
||||
"Berühre eine Technik, um ihre Hinweise zu lesen.", 0.4, Color(0.9, 0.9, 1))
|
||||
var ids := TechDB.ids()
|
||||
for i in range(ids.size()):
|
||||
var reihe := i / 6
|
||||
var spalte := i % 6
|
||||
var p := Vector3(-12.5 + spalte * 5.0, INNEN_Y, -6.5 + reihe * 7.0)
|
||||
var t := TechDB.by_id(ids[i])
|
||||
Prims.cyl(innen, p + Vector3(0, 0.5, 0), 0.8, 1.0, Color(0.30, 0.26, 0.45))
|
||||
var kristall := Prims.box(innen, p + Vector3(0, 1.8, 0), Vector3(0.9, 0.9, 0.9),
|
||||
t["farbe"], false, 1.4)
|
||||
kristall.rotation = Vector3(0.6, 0.8, 0.0)
|
||||
_regale[ids[i]] = kristall
|
||||
Prims.label(innen, p + Vector3(0, 3.2 + float(reihe) * 0.6, 0), t["name"], 0.36, Color(1, 1, 1))
|
||||
_interaktion(innen, p + Vector3(0, 1.2, 0), "technik", ids[i], t["name"])
|
||||
|
||||
|
||||
func _gebaeude_missionshalle() -> void:
|
||||
var innen := _gebaeude("Missionshalle",
|
||||
Vector3(0, 0, -28), Vector3(18, 5, 14),
|
||||
Vector3(90, INNEN_Y, 0), Vector3(26, 6, 20),
|
||||
Color(0.74, 0.55, 0.48))
|
||||
Prims.label(innen, Vector3(90, INNEN_Y + 5.0, -8.5),
|
||||
"Menschen, deren Traum feststeckt.", 0.42, Color(1, 0.92, 0.8))
|
||||
for i in range(HumanDB.LIST.size()):
|
||||
var h: Dictionary = HumanDB.LIST[i]
|
||||
var p := Vector3(90.0 + (float(i) - 1.5) * 7.0, INNEN_Y, -3.0)
|
||||
Prims.cyl(innen, p + Vector3(0, 0.4, 0), 1.2, 0.8, Color(0.35, 0.28, 0.26))
|
||||
var saeule := Prims.box(innen, p + Vector3(0, 2.0, 0), Vector3(1.4, 3.2, 1.4),
|
||||
h["farbe"], false, 0.8)
|
||||
var sphere := Prims.sphere(innen, p + Vector3(0, 4.1, 0), 0.55,
|
||||
(h["farbe"] as Color).lightened(0.4), 1.6)
|
||||
var lab := Prims.label(innen, p + Vector3(0, 5.2, 0), h["name"], 0.32, Color(1, 1, 1))
|
||||
_stelen[h["id"]] = {"saeule": saeule, "kugel": sphere, "label": lab}
|
||||
_interaktion(innen, p + Vector3(0, 1.5, 0), "mission", h["id"], h["name"])
|
||||
|
||||
|
||||
func _gebaeude_meditation() -> void:
|
||||
var innen := _gebaeude("Meditationskammer",
|
||||
Vector3(24, 0, -16), Vector3(14, 5, 14),
|
||||
Vector3(-90, INNEN_Y, 0), Vector3(20, 6, 18),
|
||||
Color(0.46, 0.66, 0.74))
|
||||
Prims.label(innen, Vector3(-90, INNEN_Y + 5.0, -7.5),
|
||||
"Übung vertieft, was du schon kannst.", 0.42, Color(0.85, 1, 1))
|
||||
Prims.cyl(innen, Vector3(-90, INNEN_Y + 0.5, -1.0), 3.0, 1.0, Color(0.24, 0.34, 0.40))
|
||||
var kugel := Prims.sphere(innen, Vector3(-90, INNEN_Y + 2.6, -1.0), 1.2,
|
||||
Color(0.55, 0.95, 1.0), 1.8)
|
||||
kugel.name = "Meditationskugel"
|
||||
_interaktion(innen, Vector3(-90, INNEN_Y + 1.5, -1.0), "vertiefen", "", "Meditationskugel")
|
||||
|
||||
|
||||
func _tor_zur_erde() -> void:
|
||||
var pos := Vector3(0, 0, 18)
|
||||
Prims.cyl(self, pos + Vector3(0, 0.3, 0), 5.0, 0.6, Color(0.35, 0.30, 0.50))
|
||||
for i in range(10):
|
||||
var a := PI * float(i) / 9.0
|
||||
Prims.box(self, pos + Vector3(cos(a) * 4.2, sin(a) * 4.2 + 0.6, 0),
|
||||
Vector3(0.7, 0.7, 0.7), Color(0.5, 0.85, 1.0), false, 1.8)
|
||||
var scheibe := Prims.cyl(self, pos + Vector3(0, 2.6, 0), 3.0, 0.2,
|
||||
Color(0.45, 0.75, 1.0, 0.28), false, 1.0)
|
||||
scheibe.rotation.x = PI * 0.5
|
||||
Prims.label(self, pos + Vector3(0, 6.4, 0), "Tor zur Erde", 0.7, Color(0.7, 0.95, 1))
|
||||
_interaktion(self, pos + Vector3(0, 1.6, 0), "erde", "", "Tor zur Erde")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- Aktualisieren
|
||||
|
||||
func _refresh() -> void:
|
||||
for id in _regale:
|
||||
var m: MeshInstance3D = _regale[id]
|
||||
var t := TechDB.by_id(id)
|
||||
if Game.knows(id):
|
||||
m.material_override = Prims.mat(t["farbe"], 2.2)
|
||||
m.scale = Vector3.ONE * (1.0 + 0.12 * Game.skill_of(id))
|
||||
else:
|
||||
m.material_override = Prims.mat((t["farbe"] as Color).darkened(0.35), 0.5)
|
||||
m.scale = Vector3.ONE * 0.75
|
||||
for id in _stelen:
|
||||
var s: Dictionary = _stelen[id]
|
||||
var h := HumanDB.by_id(id)
|
||||
var lab: Label3D = s["label"]
|
||||
if Game.completed.has(id):
|
||||
s["kugel"].material_override = Prims.mat(Color(0.5, 1.0, 0.6), 2.4)
|
||||
lab.text = h["name"] + "\n★ erfüllt"
|
||||
elif Game.active_mission == id:
|
||||
s["kugel"].material_override = Prims.mat(Color(1, 0.85, 0.35), 2.4)
|
||||
lab.text = h["name"] + "\naktive Mission · %d %%" % int(Game.mission_progress(id))
|
||||
else:
|
||||
s["kugel"].material_override = Prims.mat((h["farbe"] as Color).lightened(0.4), 1.2)
|
||||
lab.text = h["name"] + "\nwartet"
|
||||
|
||||
Reference in New Issue
Block a user