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

265 lines
12 KiB
GDScript

extends "res://scene_base.gd"
## Szene Arena: Steinboden bei Nacht, runde Kampfarena, Mondlicht von oben, Fackeln an den Seiten.
const STONE := Color("4a5260")
const STONE_DARK := Color("262c36")
const IRON := Color("8a94a4")
const INK := Color("e8ecf4")
const MUTED := Color("98a2b4")
const BANNER_OPP := Color("7a2630")
const BANNER_OWN := Color("24467a")
const C := Vector2(640, 400)
func build_env() -> void:
light_dir = Vector2(0, 8)
layer(linear_tex(STONE_DARK, darker(STONE_DARK, 0.6)), Rect2(Vector2.ZERO, size))
layer(noise_tex(320, 200, "cellfill", 0.06, 11), Rect2(Vector2.ZERO, size), Color(STONE, 0.35)) # Platten
layer(noise_tex(640, 400, "cell", 0.05, 11), Rect2(Vector2.ZERO, size), Color(0, 0, 0, 0.5)) # Fugen
layer(noise_tex(256, 256, "simplex", 0.08, 4), Rect2(Vector2.ZERO, size), Color(1, 1, 1, 0.06))
light(Vector2(640, 120), 820, Color("b8d0ff"), 0.30) # Mond
light(Vector2(30, 420), 300, Color("ff9a40"), 0.45) # Fackeln
light(Vector2(1250, 420), 300, Color("ff9a40"), 0.45)
for e in ["Feuer", "Wasser", "Erde", "Luft"]: # Runenlicht
light(rune_pos(e), 90, ELEM[e], 0.6)
vignette_layer(0.75)
func rune_pos(e: String) -> Vector2:
match e:
"Feuer": return C + Vector2(-258, 0)
"Erde": return C + Vector2(-190, 0)
"Wasser": return C + Vector2(258, 0)
return C + Vector2(190, 0)
func _draw() -> void:
_arena()
_opponent()
_boards()
_player()
_preview()
txt("Dinger · Szene: Arena", 12, MUTED, Vector2(20, 782), "midleft")
# --- Arena -------------------------------------------------------------------------------
func _arena() -> void:
circle(C, 340, Color(0, 0, 0, 0.35))
circle(C, 330, Color(STONE, 0.55))
ring(C, 330, darker(STONE, 0.5), 10)
ring(C, 335, Color(1, 1, 1, 0.08), 1)
ring(C, 325, Color(0, 0, 0, 0.35), 2)
ring(C, 300, Color(0, 0, 0, 0.25), 3)
ring(C, 301, Color(1, 1, 1, 0.05), 1)
# Mittellinie und Kernstein
draw_line(C + Vector2(-300, 0), C + Vector2(-70, 0), Color(0, 0, 0, 0.45), 3, true)
draw_line(C + Vector2(70, 0), C + Vector2(300, 0), Color(0, 0, 0, 0.45), 3, true)
draw_line(C + Vector2(-300, 1), C + Vector2(-70, 1), Color(1, 1, 1, 0.08), 1, true)
draw_line(C + Vector2(70, 1), C + Vector2(300, 1), Color(1, 1, 1, 0.08), 1, true)
circle(C, 62, Color(0, 0, 0, 0.35))
circle(C, 54, darker(STONE, 0.8))
ring(C, 54, darker(STONE, 0.45), 4)
ring(C, 44, Color(IRON, 0.5), 2)
var pts := PackedVector2Array()
for i in 6:
var a := -PI / 2 + i * PI / 3
pts.append(C + Vector2(cos(a), sin(a)) * 30)
draw_colored_polygon(pts, Color("1a2030"))
for i in 6:
draw_line(C, pts[i], Color(IRON, 0.5), 1, true)
for e in ["Feuer", "Wasser", "Erde", "Luft"]:
var p := rune_pos(e)
circle(p, 22, Color("12161e"))
ring(p, 22, darker(STONE, 0.6), 3)
glyph(e, p, 24, lighter(ELEM[e], 0.35))
# Steinsims für die Hand
var ledge := Rect2(300, 652, 680, 148)
rr(ledge, 6, Color("1c2129"))
border(ledge, 6, Color(0, 0, 0, 0.6), 3)
draw_line(ledge.position + Vector2(4, 2), Vector2(ledge.end.x - 4, ledge.position.y + 2), Color(1, 1, 1, 0.12), 2, true)
func slot(rect: Rect2) -> void:
rr(rect, 4, Color(0, 0, 0, 0.3))
inset(rect, 4, 0.8)
border(rect, 4, Color(1, 1, 1, 0.07), 1)
border(rect.grow(-5), 3, Color(0, 0, 0, 0.25), 1)
# --- Karten als Steintafeln ------------------------------------------------------------------
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 := 6 if big else 5
if rare_col != null:
glow(rect, rad, rare_col, 9, 0.7)
shadow(rect, rad, 12 if big else 8, 0.6)
grad(rect, rad, lighter(STONE, 0.12), darker(STONE, 0.6))
border(rect, rad, Color(0, 0, 0, 0.7), 2)
draw_line(rect.position + Vector2(4, 2.5), Vector2(rect.end.x - 4, rect.position.y + 2.5), Color(1, 1, 1, 0.2), 1.5, true) # Lichtkante
var inner := rect.grow(-6)
# Fenster in Elementfarbe (Glas)
var pic := Rect2(inner.position, Vector2(inner.size.x, inner.size.y * (0.42 if big else 0.52)))
rr(pic, 4, darker(base, 0.5))
grad(pic.grow(-2), 3, lighter(base, 0.1), darker(base, 0.45))
inset(pic, 4, 1.0)
var gc := pic.get_center()
var gs := pic.size.x * (0.55 if big else 0.6)
circle(gc, gs * 0.45, Color(lighter(base, 0.5), 0.3))
glyph(elem, gc + Vector2(0, 3), gs, Color(0, 0, 0, 0.4))
glyph(elem, gc, gs, lighter(base, 0.5))
# Gemeißeltes Namensfeld
var fs := 14 if big else 11
var band := Rect2(inner.position.x, pic.end.y + 4, inner.size.x, fs + 10)
rr(band, 3, Color("161a22"))
inset(band, 3, 0.9)
txt(fit(name, fs, band.size.x - 12), 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 + 24, y), 9, KW[elem], lighter(base, 0.45), Color("161a22"))
txt(KW[elem], 12, INK, Vector2(inner.position.x + 40, y), "midleft")
var box := Rect2(inner.position.x + 4, y + 14, inner.size.x - 8, rect.end.y - 52 - (y + 14))
rr(box, 3, Color("161a22"))
inset(box, 3, 0.7)
txt("Greift zweimal je Zug", 11, INK, box.get_center())
if rare_col != null:
border(rect.grow(-3), rad - 1, Color(rare_col, 0.8), 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("d89a20"), fsz, IRON)
badge(rect.position + Vector2(rect.size.x - m, rect.size.y - m), r, str(hp), Color("3a78d8"), fsz, IRON)
crystal(rect.position + Vector2(m, m), r + 1, str(cost), fsz, Color("3a6ad0"), IRON)
func card_back(rect: Rect2) -> void:
shadow(rect, 5, 8, 0.6)
grad(rect, 5, lighter(STONE, 0.08), darker(STONE, 0.55))
border(rect, 5, Color(0, 0, 0, 0.7), 2)
var inner := rect.grow(-8)
rr(inner, 3, Color("1a2030"))
inset(inner, 3, 0.9)
var c := rect.get_center()
ring(c, 22, Color(IRON, 0.8), 2)
var pts := PackedVector2Array()
for i in 6:
var a := -PI / 2 + i * PI / 3
pts.append(c + Vector2(cos(a), sin(a)) * 14)
draw_colored_polygon(pts, Color(IRON, 0.5))
ring(c, 6, Color("1a2030"), 2)
func pedestal(rect: Rect2, count: String, label := "") -> void:
var base := Rect2(rect.position.x - 12, rect.end.y - 10, rect.size.x + 24, 26)
shadow(base, 3, 8, 0.6)
grad(base, 3, lighter(STONE, 0.05), darker(STONE, 0.5), 6)
border(base, 3, Color(0, 0, 0, 0.7), 2)
for i in range(5, 0, -1):
var r := Rect2(rect.position + Vector2(0, -i * 2.2), rect.size)
rr(r, 5, Color("2a3140"))
border(r, 5, Color(0, 0, 0, 0.5), 1)
card_back(Rect2(rect.position + Vector2(0, -12), rect.size))
if label != "":
rr(Rect2(rect.position.x + 12, rect.end.y - 64, rect.size.x - 24, 44), 4, Color("12161e"))
txt_shadow(label, 15, INK, Vector2(rect.get_center().x, rect.end.y - 52), "center", true)
txt("◆ 0", 14, Color("8ab8ff"), Vector2(rect.get_center().x, rect.end.y - 32))
txt_shadow(count, 13, INK, Vector2(rect.get_center().x, base.get_center().y + 1), "center", true)
# --- Banner, Runensteine ------------------------------------------------------------------------
func banner(pos: Vector2, col: Color, name: String, life: String, elem: String, mana_full: int, active := false) -> void:
var w := 150.0
var h := 170.0
var pts := PackedVector2Array([pos, pos + Vector2(w, 0), pos + Vector2(w, h - 28), pos + Vector2(w / 2, h), pos + Vector2(0, h - 28)])
var sh := PackedVector2Array()
for p in pts:
sh.append(p + Vector2(0, 8))
draw_colored_polygon(sh, Color(0, 0, 0, 0.45))
draw_colored_polygon(pts, darker(col, 0.8))
var in_pts := PackedVector2Array([pos + Vector2(8, 8), pos + Vector2(w - 8, 8), pos + Vector2(w - 8, h - 32), pos + Vector2(w / 2, h - 12), pos + Vector2(8, h - 32)])
draw_colored_polygon(in_pts, col)
var closed := pts.duplicate()
closed.append(pts[0])
draw_polyline(closed, Color(0, 0, 0, 0.6), 2, true)
# Stange
rr(Rect2(pos.x - 10, pos.y - 8, w + 20, 10), 3, darker(IRON, 0.6))
draw_line(Vector2(pos.x - 8, pos.y - 5), Vector2(pos.x + w + 8, pos.y - 5), lighter(IRON, 0.15), 2, true)
# Emblem
var c := pos + Vector2(w / 2, 58)
circle(c, 34, Color(0, 0, 0, 0.35))
circle(c, 30, darker(col, 0.5))
glyph(elem, c + Vector2(0, 1), 36, lighter(ELEM[elem], 0.4), Color(0, 0, 0, 0.5))
metal_ring(c, 30, 3, IRON if not active else lighter(IRON, 0.2))
txt_shadow(name, 15, INK, pos + Vector2(w / 2, 108), "center", true)
badge(pos + Vector2(w / 2 - 34, 134), 15, life, Color("c83030"), 15, IRON)
for i in 3:
var p := pos + Vector2(w / 2 + 6 + i * 20, 134)
circle(p, 7, Color("3a6ad0") if i < mana_full else Color("1a2030"))
ring(p, 7, darker(IRON, 0.7), 1.5)
func rune_stone(rect: Rect2, elem: String, filled: int, played: String) -> void:
var col: Color = ELEM[elem]
shadow(rect, 10, 6, 0.6)
grad(rect, 10, lighter(STONE, 0.05), darker(STONE, 0.5), 8)
border(rect, 10, Color(0, 0, 0, 0.7), 2)
draw_line(rect.position + Vector2(10, 2.5), Vector2(rect.end.x - 10, rect.position.y + 2.5), Color(1, 1, 1, 0.15), 1.5, true)
circle(Vector2(rect.position.x + 20, rect.get_center().y), 13, Color(col, 0.35))
glyph(elem, Vector2(rect.position.x + 20, rect.get_center().y), 18, lighter(col, 0.4))
txt(elem, 13, INK, Vector2(rect.position.x + 40, rect.get_center().y), "midleft", true)
for k in 2:
keyword_icon(Vector2(rect.position.x + 118 + k * 24, rect.get_center().y), 8, KW[elem], lighter(col, 0.4) if k < filled else Color(col, 0.3), Color("161a22"))
txt(played, 15, lighter(col, 0.4), Vector2(rect.end.x - 12, rect.get_center().y), "midright", true)
func button(rect: Rect2, label: String) -> void:
shadow(rect, 4, 5, 0.5)
grad(rect, 4, lighter(STONE, 0.1), darker(STONE, 0.55), 8)
border(rect, 4, Color(0, 0, 0, 0.7), 2)
draw_line(rect.position + Vector2(4, 2.5), Vector2(rect.end.x - 4, rect.position.y + 2.5), Color(1, 1, 1, 0.2), 1.5, true)
txt_shadow(label, 13, INK, rect.get_center(), "center", true)
# --- Anordnung ---------------------------------------------------------------------------------
func _opponent() -> void:
banner(Vector2(50, 20), BANNER_OPP, "Gegner", "35", "Feuer", 0)
rune_stone(Rect2(30, 220, 210, 36), "Feuer", 1, "1")
button(Rect2(30, 268, 210, 30), "Überspringen")
for i in 4:
var r := Rect2(426 + i * 114, 12, 100, 128)
card_back(r)
pedestal(Rect2(1090, 40, 110, 150), "35")
func _boards() -> void:
for j in 5:
var r := Rect2(342 + j * 122, 172, 110, 140)
if j == 0:
card(r, "Schwelender Drache", "Feuer", 1, 0, 5)
else:
slot(r)
for j in 5:
var r := Rect2(342 + j * 122, 488, 110, 140)
if j == 0:
card(r, "Rieselnder Geist", "Wasser", 1, 1, 2)
else:
slot(r)
func _player() -> void:
banner(Vector2(50, 560), BANNER_OWN, "Spieler", "30", "Wasser", 1, true)
rune_stone(Rect2(30, 500, 210, 36), "Wasser", 1, "1")
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]
card(Rect2(350 + i * 118, 650, 110, 140), h[0], h[1], h[2], h[3], h[4], false, h[5])
pedestal(Rect2(1090, 610, 110, 150), "35", "Ziehen")
func _preview() -> void:
card(Rect2(1062, 260, 176, 246), "Glimmender Wolf", "Feuer", 1, 1, 3, true, Color("d0d8e4"))