Files
assets-generator/preview/scene_taverne.gd
2026-10-10 16:35:28 +02:00

252 lines
11 KiB
GDScript

extends "res://scene_base.gd"
## Szene Taverne: Holztisch, Filz-Spielmatte, Messing, warmes Lampenlicht von oben links.
const WOOD := Color("5a3a22")
const WOOD_LIGHT := Color("8a5a34")
const FELT := Color("3c5e46")
const BRASS := Color("c9a046")
const DARK := Color("1a120c")
const INK := Color("f0e2c0")
const MUTED := Color("b8a888")
const MAT := Rect2(250, 60, 780, 690)
func build_env() -> void:
light_dir = Vector2(4, 7)
# Tisch: Holz mit waagerechter Maserung, zwei Lagen
layer(linear_tex(WOOD, darker(WOOD, 0.7)), Rect2(Vector2.ZERO, size))
layer(noise_tex(48, 800, "simplex", 0.08, 3), Rect2(Vector2.ZERO, size), Color(WOOD_LIGHT, 0.55))
layer(noise_tex(256, 256, "simplex", 0.05, 7), Rect2(Vector2.ZERO, size), Color(0, 0, 0, 0.25))
# Spielmatte aus Filz mit leichter Struktur
layer(linear_tex(FELT, darker(FELT, 0.75)), MAT.grow(-6))
layer(noise_tex(390, 345, "simplex", 0.9, 5), MAT.grow(-6), Color(1, 1, 1, 0.07))
# Lampenlicht von oben, Kerze beim eigenen Stapel
light(Vector2(560, 160), 760, Color("ffd9a0"), 0.42)
light(Vector2(640, 420), 520, Color("ffe8c0"), 0.22)
light(Vector2(1150, 720), 220, Color("ffb060"), 0.35)
vignette_layer(0.7)
func _draw() -> void:
_mat()
_opponent()
_boards()
_player()
_preview()
txt("Dinger · Szene: Taverne", 12, MUTED, Vector2(20, 782), "midleft")
# --- Matte und Zonen ------------------------------------------------------------------
func _mat() -> void:
shadow(MAT, 14, 18, 0.6)
border(MAT, 14, darker(WOOD, 0.5), 6) # Lederkante
border(MAT.grow(-3), 12, Color("3a2816"), 2)
engrave(MAT.grow(-14), 10, Color(0, 0, 0, 0.35), Color(1, 1, 1, 0.06)) # Naht
# Zonen als eingedrückte Felder
for z in [Rect2(330, 170, 620, 160), Rect2(330, 430, 620, 160)]:
rr(z, 10, Color(0, 0, 0, 0.18))
inset(z, 10, 0.6)
# Mittellinie mit Elementkompass
draw_line(Vector2(290, 400), Vector2(560, 400), Color(0, 0, 0, 0.4), 2, true)
draw_line(Vector2(720, 400), Vector2(990, 400), Color(0, 0, 0, 0.4), 2, true)
draw_line(Vector2(290, 401), Vector2(560, 401), Color(1, 1, 1, 0.08), 1, true)
draw_line(Vector2(720, 401), Vector2(990, 401), Color(1, 1, 1, 0.08), 1, true)
var c := Vector2(640, 400)
circle(c, 58, Color(0, 0, 0, 0.25))
ring(c, 58, Color(0, 0, 0, 0.35), 3)
ring(c, 59, Color(1, 1, 1, 0.07), 1)
metal_ring(c, 44, 3, darker(BRASS, 0.8))
var dirs := {"Feuer": Vector2(0, -1), "Wasser": Vector2(0, 1), "Erde": Vector2(-1, 0), "Luft": Vector2(1, 0)}
for e in dirs:
glyph(e, c + dirs[e] * 26, 20, Color(ELEM[e], 0.85))
func slot(rect: Rect2) -> void:
rr(rect, 8, Color(0, 0, 0, 0.22))
inset(rect, 8, 0.7)
border(rect, 8, Color(1, 1, 1, 0.05), 1)
# --- Karten ---------------------------------------------------------------------------
func card(rect: Rect2, name: String, elem: String, cost: int, atk: int, hp: int, big := false, rare_col = null) -> void:
var base: Color = ELEM[elem]
var rad := 10 if big else 8
if rare_col != null:
glow(rect, rad, rare_col, 9, 0.7)
shadow(rect, rad, 10 if big else 7, 0.55)
rr(rect, rad, DARK)
var inner := rect.grow(-3)
grad(inner, rad - 2, lighter(base, 0.08), darker(base, 0.55))
# Bildfeld mit Lichtkern hinter dem Symbol
var pic := Rect2(inner.position + Vector2(5, 5), Vector2(inner.size.x - 10, inner.size.y * (0.40 if big else 0.5)))
rr(pic, rad - 4, Color(0, 0, 0, 0.18))
inset(pic, rad - 4, 0.6)
var gc := pic.get_center()
var gs := pic.size.x * (0.55 if big else 0.6)
circle(gc, gs * 0.42, Color(lighter(base, 0.45), 0.25))
glyph(elem, gc + Vector2(2, 3), gs, Color(0, 0, 0, 0.35))
glyph(elem, gc, gs, lighter(base, 0.42))
# Namensband
var fs := 14 if big else 11
var band := Rect2(inner.position.x - 2, pic.end.y + 3, inner.size.x + 4, fs + 12)
ribbon(band, DARK, BRASS if rare_col == null else rare_col)
txt(fit(name, fs, band.size.x - 24), fs, INK if rare_col == null else lighter(rare_col, 0.3), band.get_center(), "center", true)
if big:
var y := band.end.y + 14
keyword_icon(Vector2(inner.position.x + 30, y), 9, KW[elem], lighter(base, 0.45))
txt(KW[elem], 12, INK, Vector2(inner.position.x + 46, y), "midleft")
var box := Rect2(inner.position.x + 8, y + 14, inner.size.x - 16, rect.end.y - 52 - (y + 14))
rr(box, 6, Color(0.05, 0.04, 0.03, 0.55))
txt("Greift zweimal je Zug", 11, INK, box.get_center())
border(inner, rad - 2, Color(BRASS if rare_col == null else rare_col, 0.9), 1)
var r := 15.0 if big else 11.0
var fsz := 17 if big else 13
var m := r + 8
badge(rect.position + Vector2(m, rect.size.y - m), r, str(atk), Color("e0a020"), fsz, BRASS)
badge(rect.position + Vector2(rect.size.x - m, rect.size.y - m), r, str(hp), Color("3a78d8"), fsz, BRASS)
crystal(rect.position + Vector2(m, m), r + 1, str(cost), fsz, Color("3a6ad0"), BRASS)
func card_back(rect: Rect2) -> void:
shadow(rect, 8, 7, 0.55)
rr(rect, 8, DARK)
var inner := rect.grow(-3)
grad(inner, 6, Color("6a2a24"), Color("30120e"))
border(inner.grow(-6), 4, Color(BRASS, 0.8), 1)
border(inner.grow(-9), 3, Color(BRASS, 0.35), 1)
var c := rect.get_center()
circle(c, 26, Color(0, 0, 0, 0.3))
metal_ring(c, 24, 2.5, BRASS)
var star := PackedVector2Array()
for i in 8:
var a := -PI / 2 + i * PI / 4
star.append(c + Vector2(cos(a), sin(a)) * (16 if i % 2 == 0 else 7))
draw_colored_polygon(star, BRASS)
circle(c, 4, DARK)
func deck(rect: Rect2, count: String, label := "") -> void:
for i in range(5, 0, -1):
var r := Rect2(rect.position + Vector2(i * 1.5, -i * 2), rect.size)
rr(r, 8, DARK)
rr(r.grow(-3), 6, Color("4a1e18"))
card_back(rect)
if label != "":
rr(Rect2(rect.position.x + 14, rect.end.y - 54, rect.size.x - 28, 40), 6, Color(0, 0, 0, 0.55))
txt_shadow(label, 15, INK, Vector2(rect.get_center().x, rect.end.y - 42), "center", true)
txt("◆ 0", 14, Color("8ab8ff"), Vector2(rect.get_center().x, rect.end.y - 24))
plaque(Rect2(rect.position.x + 36, rect.position.y - 14, rect.size.x - 72, 24), count, 13)
# --- Messing-Plaketten, Helden -------------------------------------------------------------
func plaque(rect: Rect2, label: String, fs := 13, col := INK) -> void:
shadow(rect, 4, 4, 0.5)
grad(rect, 4, lighter(BRASS, 0.08), darker(BRASS, 0.6), 8)
border(rect, 4, darker(BRASS, 0.4), 1)
rr(rect.grow(-4), 2, Color("2a1c10"))
txt(label, fs, col, rect.get_center(), "center", true)
func element_plaque(rect: Rect2, elem: String, filled: int, played: String) -> void:
shadow(rect, 4, 4, 0.5)
grad(rect, 4, lighter(BRASS, 0.08), darker(BRASS, 0.6), 8)
border(rect, 4, darker(BRASS, 0.4), 1)
var in_r := rect.grow(-4)
rr(in_r, 2, Color("2a1c10"))
var col: Color = ELEM[elem]
glyph(elem, Vector2(in_r.position.x + 16, in_r.get_center().y), 18, col)
txt(elem, 13, INK, Vector2(in_r.position.x + 34, in_r.get_center().y), "midleft", true)
for k in 2:
keyword_icon(Vector2(in_r.position.x + 112 + k * 24, in_r.get_center().y), 8, KW[elem], lighter(col, 0.4) if k < filled else Color(col, 0.3))
txt(played, 15, lighter(col, 0.4), Vector2(in_r.end.x - 12, in_r.get_center().y), "midright", true)
## Held: Medaillon mit Messingring, Lebensgem links unten, Name auf Plakette, Mana als Kristalle.
func hero(c: Vector2, name: String, life: String, elem: String, mana_full: int, mana_max: int, active := false) -> void:
circle(c + light_dir, 50, Color(0, 0, 0, 0.5))
circle(c, 48, Color("2a1c10"))
circle(c, 44, Color(ELEM[elem], 0.35))
inset(Rect2(c - Vector2(44, 44), Vector2(88, 88)), 44, 0.8)
glyph(elem, c + Vector2(0, 2), 50, Color(lighter(ELEM[elem], 0.4), 0.9), Color(0, 0, 0, 0.5))
metal_ring(c, 48, 5, lighter(BRASS, 0.05) if active else darker(BRASS, 0.8))
if active:
ring(c, 54, Color("ffd980"), 2)
plaque(Rect2(c.x - 60, c.y + 54, 120, 26), name, 14)
badge(c + Vector2(-42, 36), 17, life, Color("c83030"), 16, BRASS)
# Mana: Kristalle in einer Reihe
for i in mana_max:
var p := Vector2(c.x - 60 + 14 + i * 20, c.y + 100)
var col := Color("3a6ad0") if i < mana_full else Color("1c2434")
var pts := PackedVector2Array()
for k in 6:
var a := -PI / 2 + k * PI / 3
pts.append(p + Vector2(cos(a), sin(a)) * 8)
draw_colored_polygon(pts, col)
var closed := pts.duplicate()
closed.append(pts[0])
draw_polyline(closed, darker(BRASS, 0.7), 1.5, true)
func button(rect: Rect2, label: String) -> void:
shadow(rect, 6, 5, 0.5)
grad(rect, 6, Color("7a5230"), Color("3e2814"), 8)
border(rect, 6, darker(BRASS, 0.6), 2)
border(rect.grow(-3), 4, Color(1, 1, 1, 0.06), 1)
txt_shadow(label, 13, INK, rect.get_center(), "center", true)
# --- Anordnung ------------------------------------------------------------------------------
func _opponent() -> void:
hero(Vector2(130, 110), "Gegner", "35", "Feuer", 0, 3)
element_plaque(Rect2(30, 240, 200, 34), "Feuer", 1, "1")
button(Rect2(30, 290, 200, 30), "Überspringen")
for i in 4:
var t := i - 1.5
var r := Rect2(430 + i * 112, 14, 100, 128)
draw_set_transform(r.get_center() + Vector2(0, t * t * 2), deg_to_rad(-t * 2.5))
card_back(Rect2(-r.size / 2, r.size))
draw_set_transform(Vector2.ZERO)
deck(Rect2(1090, 40, 110, 150), "35")
func _boards() -> void:
for j in 5:
var r := Rect2(340 + j * 122, 180, 110, 140)
if j == 0:
card(r, "Schwelender Drache", "Feuer", 1, 0, 5)
else:
slot(r)
for j in 5:
var r := Rect2(340 + j * 122, 440, 110, 140)
if j == 0:
card(r, "Rieselnder Geist", "Wasser", 1, 1, 2)
else:
slot(r)
func _player() -> void:
hero(Vector2(130, 600), "Spieler", "30", "Wasser", 1, 3, true)
element_plaque(Rect2(30, 470, 200, 34), "Wasser", 1, "1")
# Hand als Fächer in einer Lederrinne
var tray := Rect2(360, 628, 560, 150)
rr(tray, 16, Color(0, 0, 0, 0.3))
inset(tray, 16, 0.8)
var hand := [["Leiser Hauch", "Luft", 0, 0, 1, null], ["Glimmender Wolf", "Feuer", 1, 1, 3, Color("d0d8e4")],
["Stiller Tropfen", "Wasser", 0, 0, 1, null], ["Fester Kiesel", "Erde", 1, 1, 1, Color("f0b030")], ["Rieselnder Geist", "Wasser", 1, 1, 2, null]]
for i in hand.size():
var h = hand[i]
var t := i - 2.0
var c := Vector2(640 + t * 104, 698 + t * t * 3)
draw_set_transform(c, deg_to_rad(t * 5))
card(Rect2(-55, -70, 110, 140), h[0], h[1], h[2], h[3], h[4], false, h[5])
draw_set_transform(Vector2.ZERO)
deck(Rect2(1090, 620, 110, 150), "35", "Ziehen")
func _preview() -> void:
card(Rect2(1062, 250, 176, 246), "Glimmender Wolf", "Feuer", 1, 1, 3, true, Color("d0d8e4"))