Resource próprio
Um Resource com class_name usado como dado tipado. Seis itens compartilham o script e cada card se redesenha pelo sinal changed.
O editor acima está rodando este projeto. Mude uma linha e ele recarrega.
Classes do Godot usadas
Resourceclass_nameResource.changedGDScript
O código
scripts/main.gd
extends Node
const ROSTER: Array = [
{title = 'Copper coin', cost = 10, power = 1, tint = '#f3d48d'},
{title = 'Oak shield', cost = 45, power = 3, tint = '#8eef97'},
{title = 'Frost dagger', cost = 80, power = 4, tint = '#8da5f3'},
{title = 'Ember ring', cost = 120, power = 2, tint = '#fc7f7f'},
{title = 'Silk cloak', cost = 60, power = 5, tint = '#8eef97'},
{title = 'Iron helm', cost = 95, power = 6, tint = '#8da5f3'},
]
const TICK: float = 0.08
# Variant and not PlaygroundItem: the playground loads the script at runtime, so the global class never registers
var items: Array = []
# index -> { cost: Label, bar: ProgressBar }
var cards: Array = []
var status: Label
var elapsed: float = 0.0
var next_index: int = 0
func _ready() -> void:
var column: VBoxContainer = _root()
var title: Label = Label.new()
title.text = 'One Resource, six items'
title.add_theme_font_size_override('font_size', 28)
column.add_child(title)
var hint: Label = Label.new()
hint.text = 'item.gd extends Resource with class_name PlaygroundItem. Every card redraws from the changed signal.'
hint.add_theme_color_override('font_color', Color('#8a90a0'))
column.add_child(hint)
var grid: GridContainer = GridContainer.new()
grid.columns = 3
grid.add_theme_constant_override('h_separation', 20)
grid.add_theme_constant_override('v_separation', 20)
column.add_child(grid)
var item_script: GDScript = Get.script('item')
for entry in ROSTER:
var item: Variant = item_script.new()
item.title = entry.title
item.cost = entry.cost
item.power = entry.power
item.tint = Color(entry.tint)
items.append(item)
grid.add_child(_card(item))
var button: Button = Button.new()
button.text = 'level up every item'
button.pressed.connect(_level_all)
column.add_child(button)
status = Label.new()
status.add_theme_color_override('font_color', Color('#8eef97'))
status.text = 'six instances of the same script, each one holding its own values'
column.add_child(status)
print('the roster levels itself up, click the button to bump all six at once')
func _process(delta: float) -> void:
elapsed += delta
if elapsed < TICK:
return
elapsed = 0.0
items[next_index].level_up()
status.text = '%s leveled up' % items[next_index].title
next_index = (next_index + 1) % items.size()
func _level_all() -> void:
for item in items:
item.level_up()
status.text = 'every item leveled up'
# binds the index and not the item: a Callable holding the Resource it is connected to leaks the pair
func _refresh(index: int) -> void:
var item: Variant = items[index]
var card: Dictionary = cards[index]
card.cost.text = 'cost %d gold' % item.cost
card.bar.value = item.power
func _card(item: Variant) -> Control:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = Color('#2a2f3d')
style.set_corner_radius_all(12)
style.set_content_margin_all(16)
var panel: PanelContainer = PanelContainer.new()
panel.custom_minimum_size = Vector2(300, 0)
panel.add_theme_stylebox_override('panel', style)
var box: VBoxContainer = VBoxContainer.new()
box.add_theme_constant_override('separation', 10)
panel.add_child(box)
var head: HBoxContainer = HBoxContainer.new()
head.add_theme_constant_override('separation', 12)
box.add_child(head)
var swatch: ColorRect = ColorRect.new()
swatch.color = item.tint
swatch.custom_minimum_size = Vector2(24, 24)
head.add_child(swatch)
var name_label: Label = Label.new()
name_label.text = item.title
name_label.add_theme_font_size_override('font_size', 20)
head.add_child(name_label)
var cost: Label = Label.new()
cost.add_theme_color_override('font_color', Color('#8a90a0'))
box.add_child(cost)
var bar: ProgressBar = ProgressBar.new()
bar.max_value = 10
bar.show_percentage = false
bar.custom_minimum_size = Vector2(0, 18)
bar.add_theme_stylebox_override('background', _bar_style(Color('#12141a')))
bar.add_theme_stylebox_override('fill', _bar_style(item.tint))
box.add_child(bar)
var index: int = cards.size()
cards.append({cost = cost, bar = bar})
item.changed.connect(_refresh.bind(index))
_refresh(index)
return panel
func _bar_style(color: Color) -> StyleBoxFlat:
var style: StyleBoxFlat = StyleBoxFlat.new()
style.bg_color = color
style.set_corner_radius_all(6)
return style
func _root() -> VBoxContainer:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var margin: MarginContainer = MarginContainer.new()
for side in ['margin_left', 'margin_right', 'margin_top', 'margin_bottom']:
margin.add_theme_constant_override(side, 56)
add_child(margin)
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var center: CenterContainer = CenterContainer.new()
margin.add_child(center)
var column: VBoxContainer = VBoxContainer.new()
column.add_theme_constant_override('separation', 18)
center.add_child(column)
return columnscripts/item.gd
extends Resource
class_name PlaygroundItem
@export var title: String = 'item'
@export var cost: int = 10
@export var power: int = 1
@export var tint: Color = Color.WHITE
func level_up() -> void:
power = mini(power + 1, 10)
cost += 15
emit_changed()