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"))