158 lines
5.6 KiB
GDScript
158 lines
5.6 KiB
GDScript
class_name BoosterScreen
|
|
extends Control
|
|
|
|
const CARD_W := 200
|
|
const CARD_H := 280
|
|
|
|
var app
|
|
var cards: Array = [] # {"card", "rarity", "upgraded", "dust"} je Karte
|
|
var revealed := {}
|
|
var coins_label: Label
|
|
var msg_label: Label
|
|
var b_buy: Button
|
|
var b_all: Button
|
|
var slots: Control
|
|
var fx_layer: Control
|
|
var fresh := {} # gerade aufgedeckt: wird umgedreht
|
|
|
|
|
|
class CardBack extends Control:
|
|
signal clicked
|
|
|
|
func _init(sz: Vector2) -> void:
|
|
size = sz
|
|
custom_minimum_size = sz
|
|
mouse_filter = Control.MOUSE_FILTER_STOP
|
|
focus_mode = Control.FOCUS_ALL
|
|
focus_entered.connect(queue_redraw)
|
|
focus_exited.connect(queue_redraw)
|
|
|
|
func _gui_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
|
accept_event()
|
|
clicked.emit()
|
|
elif has_focus() and event.is_action_pressed("ui_accept"):
|
|
accept_event()
|
|
clicked.emit()
|
|
|
|
func _draw() -> void:
|
|
var rect := Rect2(Vector2.ZERO, size)
|
|
draw_style_box(Style.box(Color("3c285a"), 8, Style.GOLD, 5 if has_focus() else 3), rect)
|
|
Style.border(self, rect.grow(-15), Color("5a3c82"), 2, 6)
|
|
Style.text(self, "?", 48, Style.GOLD, size / 2, "center", true)
|
|
|
|
|
|
func slot_rect(i: int) -> Rect2:
|
|
var gap := 20
|
|
var x0 := (1280 - Profile.BOOSTER_SIZE * CARD_W - (Profile.BOOSTER_SIZE - 1) * gap) / 2
|
|
return Rect2(x0 + i * (CARD_W + gap), 230, CARD_W, CARD_H)
|
|
|
|
|
|
func _ready() -> void:
|
|
Style.header(self, "Booster", func(): app.show_screen(MenuScreen.new()))
|
|
coins_label = Style.chip(self, "", Rect2(860, 26, 240, 38))
|
|
fx_layer = Control.new()
|
|
fx_layer.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(fx_layer)
|
|
slots = Control.new()
|
|
slots.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
add_child(slots)
|
|
msg_label = Style.label(self, "", 17, Style.RED, Rect2(0, 640, 1280, 22), "center")
|
|
b_buy = Style.button(self, "Booster kaufen (%d Münzen)" % Profile.BOOSTER_COST, Rect2(370, 690, 330, 52), buy, Color("5a4628"))
|
|
b_buy.add_theme_font_size_override("font_size", 20)
|
|
b_all = Style.button(self, "Alle aufdecken", Rect2(720, 690, 200, 52), reveal_all)
|
|
refresh()
|
|
|
|
|
|
func _input(event: InputEvent) -> void:
|
|
if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE:
|
|
app.show_screen(MenuScreen.new())
|
|
|
|
|
|
func buy() -> void:
|
|
var p: Profile = app.profile
|
|
var got: Array = p.open_booster()
|
|
if got.is_empty():
|
|
msg_label.text = "Nicht genug Münzen"
|
|
msg_label.add_theme_color_override("font_color", Style.RED)
|
|
return
|
|
app.save()
|
|
app.sfx.play("play")
|
|
cards = got
|
|
revealed = {}
|
|
msg_label.text = ""
|
|
refresh()
|
|
|
|
|
|
func reveal(i: int) -> void:
|
|
revealed[i] = true
|
|
fresh = {i: 0.0}
|
|
app.sfx.play("combo" if cards[i].rarity != "Common" else "click")
|
|
refresh()
|
|
|
|
|
|
func reveal_all() -> void:
|
|
fresh = {}
|
|
var k := 0
|
|
for i in Profile.BOOSTER_SIZE:
|
|
if not revealed.has(i):
|
|
fresh[i] = k * 0.12
|
|
k += 1
|
|
revealed[i] = true
|
|
app.sfx.play("play")
|
|
refresh()
|
|
|
|
|
|
## Umdrehen: die Karte wächst aus der Mitte; seltene Stufen blitzen in ihrer Farbe auf.
|
|
func flip(v: CardView, delay: float, rarity: String) -> void:
|
|
if not Style.animations:
|
|
return
|
|
v.scale.x = 0.0
|
|
var tw := create_tween()
|
|
tw.tween_interval(delay)
|
|
tw.tween_property(v, "scale:x", 1.0, 0.18).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
|
|
if rarity == "Common":
|
|
return
|
|
var burst := Style.panel(fx_layer, Rect2(v.position, v.size).grow(6), Color(Cards.RARITY_COLORS[rarity], 0.6), 12)
|
|
burst.pivot_offset = burst.size / 2
|
|
burst.modulate.a = 0.0
|
|
var bt := create_tween()
|
|
bt.tween_interval(delay + 0.1)
|
|
bt.tween_property(burst, "modulate:a", 1.0, 0.05)
|
|
bt.parallel().tween_property(burst, "scale", Vector2(1.25, 1.25), 0.45).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)
|
|
bt.tween_property(burst, "modulate:a", 0.0, 0.3)
|
|
bt.tween_callback(burst.queue_free)
|
|
|
|
|
|
func refresh() -> void:
|
|
var p: Profile = app.profile
|
|
coins_label.text = "Münzen: %d" % p.coins
|
|
b_buy.disabled = p.coins < Profile.BOOSTER_COST
|
|
b_all.disabled = cards.is_empty() or revealed.size() >= Profile.BOOSTER_SIZE
|
|
Style.clear(slots)
|
|
for i in Profile.BOOSTER_SIZE:
|
|
var r := slot_rect(i)
|
|
if cards.is_empty():
|
|
Style.panel(slots, r, Style.PANEL, 8, Style.PANEL_LIGHT, 2)
|
|
elif revealed.has(i):
|
|
var res: Dictionary = cards[i]
|
|
var c: Cards.Card = res.card
|
|
var v := CardView.new(c.leveled(Cards.RARITIES.find(res.rarity)), r.size, false, res.rarity)
|
|
v.position = r.position
|
|
slots.add_child(v)
|
|
if fresh.has(i):
|
|
flip(v, fresh[i], res.rarity)
|
|
Style.label(slots, tr(res.rarity), 16, Cards.RARITY_COLORS[res.rarity], Rect2(r.position.x, r.end.y + 8, r.size.x, 24), "center", true)
|
|
if res.get("new", false):
|
|
Style.label(slots, "Neu!", 16, Style.GOLD, Rect2(r.position.x, r.end.y + 32, r.size.x, 24), "center", true)
|
|
elif res.upgraded:
|
|
Style.label(slots, "Aufgewertet", 16, Style.GREEN, Rect2(r.position.x, r.end.y + 32, r.size.x, 24), "center", true)
|
|
else:
|
|
Style.label(slots, "+%d Staub" % res.dust, 14, Style.MUTED, Rect2(r.position.x, r.end.y + 32, r.size.x, 24), "center")
|
|
else:
|
|
var back := CardBack.new(r.size)
|
|
back.position = r.position
|
|
back.clicked.connect(reveal.bind(i))
|
|
slots.add_child(back)
|
|
fresh = {}
|