252 lines
11 KiB
GDScript
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"))
|