Files
dreamer-game/scripts/prims.gd
2026-08-30 11:50:09 +02:00

135 lines
4.1 KiB
GDScript

class_name Prims
## Kleine Helfer, um die Welt aus Godot-Primitiven zusammenzusetzen.
static func mat(c: Color, emis: float = 0.0, rough: float = 0.85) -> StandardMaterial3D:
var m := StandardMaterial3D.new()
m.albedo_color = c
m.roughness = rough
m.metallic = 0.0
if emis > 0.0:
m.emission_enabled = true
m.emission = c
m.emission_energy_multiplier = emis
if c.a < 1.0:
m.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
return m
static func box(parent: Node, pos: Vector3, size: Vector3, c: Color,
collide: bool = true, emis: float = 0.0) -> MeshInstance3D:
var mi := MeshInstance3D.new()
var bm := BoxMesh.new()
bm.size = size
mi.mesh = bm
mi.material_override = mat(c, emis)
mi.position = pos
parent.add_child(mi)
if collide:
_add_box_body(mi, size)
return mi
static func _add_box_body(mi: MeshInstance3D, size: Vector3) -> void:
var sb := StaticBody3D.new()
var cs := CollisionShape3D.new()
var sh := BoxShape3D.new()
sh.size = size
cs.shape = sh
sb.add_child(cs)
mi.add_child(sb)
static func cyl(parent: Node, pos: Vector3, radius: float, height: float, c: Color,
collide: bool = true, emis: float = 0.0) -> MeshInstance3D:
var mi := MeshInstance3D.new()
var cm := CylinderMesh.new()
cm.top_radius = radius
cm.bottom_radius = radius
cm.height = height
mi.mesh = cm
mi.material_override = mat(c, emis)
mi.position = pos
parent.add_child(mi)
if collide:
var sb := StaticBody3D.new()
var cs := CollisionShape3D.new()
var sh := CylinderShape3D.new()
sh.radius = radius
sh.height = height
cs.shape = sh
sb.add_child(cs)
mi.add_child(sb)
return mi
static func sphere(parent: Node, pos: Vector3, radius: float, c: Color,
emis: float = 0.0) -> MeshInstance3D:
var mi := MeshInstance3D.new()
var sm := SphereMesh.new()
sm.radius = radius
sm.height = radius * 2.0
mi.mesh = sm
mi.material_override = mat(c, emis)
mi.position = pos
parent.add_child(mi)
return mi
static func capsule(parent: Node, pos: Vector3, radius: float, height: float, c: Color) -> MeshInstance3D:
var mi := MeshInstance3D.new()
var cm := CapsuleMesh.new()
cm.radius = radius
cm.height = height
mi.mesh = cm
mi.material_override = mat(c)
mi.position = pos
parent.add_child(mi)
return mi
static func label(parent: Node, pos: Vector3, text: String, size: float = 0.35,
c: Color = Color.WHITE) -> Label3D:
var l := Label3D.new()
l.text = text
l.font_size = 96
l.pixel_size = size / 96.0
l.position = pos
l.billboard = BaseMaterial3D.BILLBOARD_ENABLED
l.no_depth_test = false
l.modulate = c
l.outline_size = 10
l.outline_modulate = Color(0, 0, 0, 0.85)
l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
parent.add_child(l)
return l
## Ein rechteckiger Raum aus vier Wänden mit einer Türlücke.
## door_dir: Vector3.FORWARD/BACK/LEFT/RIGHT -- auf welcher Seite die Lücke sitzt.
static func room(parent: Node, center: Vector3, size: Vector3, wall_c: Color,
floor_c: Color, door_dir: Vector3, door_w: float = 3.0,
with_floor: bool = true) -> void:
var t := 0.4
var h := size.y
if with_floor:
box(parent, center + Vector3(0, -0.1, 0), Vector3(size.x, 0.2, size.z), floor_c)
var seiten: Array[Vector3] = [Vector3.FORWARD, Vector3.BACK, Vector3.LEFT, Vector3.RIGHT]
for d in seiten:
var quer := absf(d.z) > 0.0 # Wand liegt entlang der X-Achse
var along: Vector3 = Vector3(1, 0, 0) if quer else Vector3(0, 0, 1)
var len_along: float = size.x if quer else size.z
var off: Vector3 = Vector3(d.x * (size.x * 0.5 - t * 0.5), h * 0.5,
d.z * (size.z * 0.5 - t * 0.5))
var voll: Vector3 = Vector3(size.x, h, t) if quer else Vector3(t, h, size.z)
if d.is_equal_approx(door_dir) and door_w > 0.0 and door_w < len_along:
var seg := (len_along - door_w) * 0.5
var seg_size: Vector3 = Vector3(seg, h, t) if quer else Vector3(t, h, seg)
for s: float in [-1.0, 1.0]:
var seg_pos: Vector3 = center + off + along * (s * (door_w * 0.5 + seg * 0.5))
box(parent, seg_pos, seg_size, wall_c)
if h >= 3.0:
var sturz: Vector3 = Vector3(door_w, h * 0.3, t) if quer else Vector3(t, h * 0.3, door_w)
box(parent, center + off + Vector3(0, h * 0.35, 0), sturz, wall_c)
else:
box(parent, center + off, voll, wall_c)