Node groups
Seventy two squares split into four groups. One call_group reaches every member of a band without a single reference.
The editor above is running this project. Change a line and it reloads.
Godot classes used
Node.add_to_groupSceneTree.call_groupPolygon2D
The code
scripts/main.gd
extends Node
const COLS: int = 12
const ROWS: int = 6
const CELL: float = 74.0
const GAP: float = 8.0
const TICK: float = 0.17
const BANDS: Array = [
{group = 'band_0', tint = '#8da5f3'},
{group = 'band_1', tint = '#8eef97'},
{group = 'band_2', tint = '#fc7f7f'},
{group = 'band_3', tint = '#f3d48d'},
]
var status: Label
var elapsed: float = 0.0
var turn: int = 0
func _ready() -> void:
_add_background()
_add_cells()
_add_panel()
print('the bands take turns on their own, every button is one call_group')
func _process(delta: float) -> void:
elapsed += delta
if elapsed < TICK:
return
elapsed = 0.0
turn += 1
if turn % 9 == 0:
_call_everyone()
return
_call_band(turn % BANDS.size())
func _call_band(index: int) -> void:
var band: Dictionary = BANDS[index]
get_tree().call_group(band.group, 'flash', Color(band.tint))
status.text = 'call_group("%s", "flash") reached %d nodes' % [band.group, get_tree().get_nodes_in_group(band.group).size()]
func _call_everyone() -> void:
get_tree().call_group('cells', 'flash', Color('#ffffff'))
status.text = 'call_group("cells", "flash") reached %d nodes' % get_tree().get_nodes_in_group('cells').size()
func _add_cells() -> void:
var cell_script: GDScript = Get.script('cell')
var step: float = CELL + GAP
var origin: Vector2 = Vector2((1280.0 - COLS * step + GAP) * 0.5, 720.0 - ROWS * step - 16.0)
for row in ROWS:
for col in COLS:
var cell: Polygon2D = Polygon2D.new()
cell.set_script(cell_script)
cell.position = origin + Vector2(col * step, row * step)
cell.add_to_group('cells')
cell.add_to_group(BANDS[(col + row) % BANDS.size()].group)
add_child(cell)
cell.setup(CELL)
func _add_panel() -> void:
var margin: MarginContainer = MarginContainer.new()
for side in ['margin_left', 'margin_top']:
margin.add_theme_constant_override(side, 40)
add_child(margin)
margin.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
var column: VBoxContainer = VBoxContainer.new()
column.add_theme_constant_override('separation', 12)
margin.add_child(column)
var title: Label = Label.new()
title.text = 'One call, seventy two nodes'
title.add_theme_font_size_override('font_size', 28)
column.add_child(title)
var hint: Label = Label.new()
hint.text = 'Every square joined a band with add_to_group. Nothing here keeps a reference to a single one of them.'
hint.add_theme_color_override('font_color', Color('#8a90a0'))
column.add_child(hint)
var row: HBoxContainer = HBoxContainer.new()
row.add_theme_constant_override('separation', 10)
column.add_child(row)
for i in BANDS.size():
var button: Button = Button.new()
button.text = BANDS[i].group
button.pressed.connect(_call_band.bind(i))
row.add_child(button)
var all: Button = Button.new()
all.text = 'cells'
all.pressed.connect(_call_everyone)
row.add_child(all)
status = Label.new()
status.add_theme_color_override('font_color', Color('#8eef97'))
status.text = 'waiting for the first call'
column.add_child(status)
func _add_background() -> void:
var background: ColorRect = ColorRect.new()
background.color = Color('#12141a')
add_child(background)
background.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)scripts/cell.gd
extends Polygon2D
const IDLE: Color = Color('#2a2f3d')
var glow: float = 0.0
var lit: Color = IDLE
func setup(size: float) -> void:
polygon = PackedVector2Array([Vector2.ZERO, Vector2(size, 0), Vector2(size, size), Vector2(0, size)])
color = IDLE
func flash(tint: Color) -> void:
lit = tint
glow = 1.0
func _process(delta: float) -> void:
if glow <= 0.0:
return
glow = maxf(glow - delta * 4.0, 0.0)
color = IDLE.lerp(lit, glow)