update
This commit is contained in:
@@ -13,6 +13,13 @@ const WEG_ABSTAND := 3.0 # Mindestluft zwischen Haus und Weg
|
||||
const KANDIDATEN := 64 # Probepunkte je Haus
|
||||
const SPINE_SCHRITT := 8.0 # Abstand der Knoten auf der Hauptachse
|
||||
|
||||
## Die Insel ist ein Hügel. Innen eben -- Dorfplatz, Hörsaal, Tor --, ab FLACH
|
||||
## steigt sie an. Wer später einzieht, wohnt weiter außen und damit höher:
|
||||
## das Dorf wächst den Hügel hinauf, und vom Platz aus sieht man, wie weit.
|
||||
const FLACH := 24.0
|
||||
const STEIGUNG := 0.30
|
||||
const GIPFEL := 36.0
|
||||
|
||||
static var FEST: Dictionary = {
|
||||
"hoersaal": {
|
||||
"name": "Hörsaal der Wege", "pos": [0.0, 34.0], "size": [16.0, 12.0],
|
||||
@@ -56,6 +63,72 @@ static var ABLAEUFE: Array = [
|
||||
]
|
||||
|
||||
|
||||
## Höhe des nackten Hangs bei diesem Abstand von der Mitte.
|
||||
static func hang(r: float) -> float:
|
||||
return clampf((r - FLACH) * STEIGUNG, 0.0, GIPFEL)
|
||||
|
||||
|
||||
## Jedes Gebäude steht auf einer ebenen Terrasse in Höhe seiner Tür -- so ist
|
||||
## die Türseite ebenerdig, die Bergseite eingegraben. Das Tor hat keine Tür;
|
||||
## seine Terrasse liegt auf Höhe der Dorfseite.
|
||||
const TOR_FLAECHE := 12.0
|
||||
const TERRASSE_RAND := 2.6 # bis zur Türschwelle davor
|
||||
const BOESCHUNG := 5.0 # so weit läuft die Terrasse in den Hang aus
|
||||
|
||||
static func terrasse(key: String) -> float:
|
||||
if not PLACES.has(key):
|
||||
return 0.0
|
||||
if key == "tor":
|
||||
var c := Orte.center(PLACES, key)
|
||||
return hang(Vector2(c.x, c.z).length() - TOR_FLAECHE * 0.5)
|
||||
var t := Orte.door(PLACES, key)
|
||||
return hang(Vector2(t.x, t.z).length())
|
||||
|
||||
|
||||
## Höhe des Bodens an dieser Stelle: Terrasse in einem Gebäude, sonst Hang.
|
||||
## Wo sich Terrassenränder überlappen, gilt das Gebäude, in dem der Punkt
|
||||
## wirklich liegt -- erst danach der Rand.
|
||||
static func hoehe_bei(x: float, z: float) -> float:
|
||||
var h := hang(Vector2(x, z).length())
|
||||
var rand_treffer := ""
|
||||
var boeschung_key := ""
|
||||
var boeschung_t := 1.0
|
||||
var reihenfolge: Array = PLACES.keys()
|
||||
reihenfolge.erase("tor")
|
||||
reihenfolge.append("tor")
|
||||
for key in reihenfolge:
|
||||
var s: Array = PLACES[key]["size"]
|
||||
var bx: float = float(s[0])
|
||||
var bz: float = float(s[1])
|
||||
if key == "tor":
|
||||
bx = TOR_FLAECHE
|
||||
bz = TOR_FLAECHE
|
||||
if bx <= 0.0 or not Game.ort_offen(key):
|
||||
continue
|
||||
var c := Orte.center(PLACES, key)
|
||||
var dx := absf(x - c.x) - bx * 0.5
|
||||
var dz := absf(z - c.z) - bz * 0.5
|
||||
if dx <= 0.0 and dz <= 0.0:
|
||||
return terrasse(key)
|
||||
if dx <= TERRASSE_RAND and dz <= TERRASSE_RAND:
|
||||
if rand_treffer == "":
|
||||
rand_treffer = key
|
||||
continue
|
||||
# außerhalb des Rands: die Terrasse läuft als Böschung in den Hang aus
|
||||
var d := maxf(dx, dz) - TERRASSE_RAND
|
||||
if d < BOESCHUNG:
|
||||
var t := d / BOESCHUNG
|
||||
if t < boeschung_t:
|
||||
boeschung_t = t
|
||||
boeschung_key = key
|
||||
if rand_treffer != "":
|
||||
return terrasse(rand_treffer)
|
||||
if boeschung_key != "":
|
||||
var tt := boeschung_t * boeschung_t * (3.0 - 2.0 * boeschung_t) # weich
|
||||
return lerpf(terrasse(boeschung_key), h, tt)
|
||||
return h
|
||||
|
||||
|
||||
static func haus_key(i: int) -> String:
|
||||
return "haus_%d" % i
|
||||
|
||||
@@ -171,11 +244,16 @@ static func _platz_frei(p: Vector3, groesse: Vector2) -> bool:
|
||||
return false
|
||||
for key in PLACES:
|
||||
var s: Array = PLACES[key]["size"]
|
||||
if float(s[0]) <= 0.0:
|
||||
var bx: float = float(s[0])
|
||||
var bz: float = float(s[1])
|
||||
if key == "tor":
|
||||
bx = TOR_FLAECHE
|
||||
bz = TOR_FLAECHE
|
||||
if bx <= 0.0:
|
||||
continue
|
||||
var c := Orte.center(PLACES, key)
|
||||
var dx: float = absf(p.x - c.x) - (groesse.x + float(s[0])) * 0.5
|
||||
var dz: float = absf(p.z - c.z) - (groesse.y + float(s[1])) * 0.5
|
||||
var dx: float = absf(p.x - c.x) - (groesse.x + bx) * 0.5
|
||||
var dz: float = absf(p.z - c.z) - (groesse.y + bz) * 0.5
|
||||
if dx < HAUS_ABSTAND and dz < HAUS_ABSTAND:
|
||||
return false
|
||||
for k in NETZ.kanten:
|
||||
@@ -249,6 +327,18 @@ static func _anschliessen(key: String) -> void:
|
||||
var an := NETZ.andocken(tuer)
|
||||
var von: Vector3 = an["punkt"]
|
||||
var linie := _route_um_haeuser(tuer, von, key)
|
||||
if not _linie_frei(linie, key):
|
||||
# Der nächste Punkt des Netzes liegt eingeklemmt. Dann den nächsten
|
||||
# Knoten nehmen, zu dem ein sauberer Weg führt -- nie durch ein Haus.
|
||||
var reihe: Array = range(NETZ.knoten.size())
|
||||
reihe.sort_custom(func(i, j) -> bool:
|
||||
return NETZ.knoten[i].distance_to(tuer) < NETZ.knoten[j].distance_to(tuer))
|
||||
for idx in reihe.slice(0, 16):
|
||||
var l2 := _route_um_haeuser(tuer, NETZ.knoten[idx], key)
|
||||
if _linie_frei(l2, key):
|
||||
linie = l2
|
||||
an = {"punkt": NETZ.knoten[idx], "knoten": idx}
|
||||
break
|
||||
var vorher := -1
|
||||
for i in range(linie.size()):
|
||||
var idx := NETZ.fuege_knoten(linie[i])
|
||||
@@ -264,17 +354,33 @@ static func _anschliessen(key: String) -> void:
|
||||
_schleife(int(ANKER[key]), key)
|
||||
|
||||
|
||||
## Schneidet diese Linie irgendwo ein Gebäude?
|
||||
static func _linie_frei(linie: Array, ausser: String) -> bool:
|
||||
for i in range(linie.size() - 1):
|
||||
if not _weg_frei(linie[i], linie[i + 1], ausser):
|
||||
return false
|
||||
return true
|
||||
|
||||
|
||||
## Weg von a nach b, der kein Haus schneidet. Frei? Dann die Gerade. Sonst
|
||||
## Dijkstra über ein grobes Raster, danach auf wenige Knicke geglättet.
|
||||
## Dijkstra über ein Raster -- erst grob, dann fein --, danach geglättet.
|
||||
static func _route_um_haeuser(a: Vector3, b: Vector3, ausser: String) -> Array:
|
||||
if _weg_frei(a, b, ausser):
|
||||
return [a, b]
|
||||
var rand := 30.0
|
||||
for schritt_start in [5.0, 2.5]:
|
||||
var weg := _route_raster(a, b, ausser, schritt_start)
|
||||
if not weg.is_empty():
|
||||
return weg
|
||||
return [a, b]
|
||||
|
||||
|
||||
static func _route_raster(a: Vector3, b: Vector3, ausser: String, schritt_start: float) -> Array:
|
||||
var rand := 34.0
|
||||
var min_x := minf(a.x, b.x) - rand
|
||||
var max_x := maxf(a.x, b.x) + rand
|
||||
var min_z := minf(a.z, b.z) - rand
|
||||
var max_z := maxf(a.z, b.z) + rand
|
||||
var schritt := 5.0
|
||||
var schritt := schritt_start
|
||||
var nx := int((max_x - min_x) / schritt) + 1
|
||||
var nz := int((max_z - min_z) / schritt) + 1
|
||||
while nx * nz > 2600:
|
||||
@@ -320,7 +426,7 @@ static func _route_um_haeuser(a: Vector3, b: Vector3, ausser: String) -> Array:
|
||||
if not offen.has(n):
|
||||
offen.append(n)
|
||||
if not gefunden:
|
||||
return [a, b]
|
||||
return []
|
||||
|
||||
var roh: Array = []
|
||||
var cur: Vector2i = ziel
|
||||
|
||||
Reference in New Issue
Block a user