008 - Agents

Agents sind wiederverwendbare Zeichen-Komponenten für den SceneGraph.

Das Konzept

Ein Agent ist ein eigenständiges "Ding, das zeichnet". Er hat eigene Parameter, eigenen State, eigene Tweakpane-UI. Du fügst ihn dem SceneGraph hinzu, und er kümmert sich um den Rest.

Warum Agents statt Funktionen? Eine Funktion drawParticles(ctx, particles) ist zustandslos – du musst die Partikel-Liste selbst verwalten. Ein ParticleManager Agent verwaltet seine Partikel intern, hat Tweakpane-Sliders für Count/Speed/Size, und du rufst nur .draw(props) auf.

Warum SceneGraph? Weil die Reihenfolge zählt. Was zuerst gezeichnet wird, liegt hinten. Ein Agent für den Hintergrund muss vor den Partikeln kommen. Der SceneGraph macht das explizit und erlaubt Umordnen zur Laufzeit.

Das Pattern: Jeder Agent hat eine statische ensureParameterSet() Methode, die Defaults ins ParameterObject schreibt. Das muss VOR dem Tweakpane-Setup passieren – sonst crasht der Exhibition-Mode (der hat keine Tweakpane).

Übersicht

                          ┌─────────────────┐
                          │   SceneGraph    │
                          └─────────────────┘
                                   │
       ┌───────────────────────────┼───────────────────────────┐
       │           │           │   │   │           │           │
       ▼           ▼           ▼   │   ▼           ▼           ▼
┌────────────┐ ┌────────────┐ ┌────┴───┐ ┌────────────┐ ┌────────────┐
│ Background │ │Background- │ │ Brush  │ │ Particle-  │ │ Particle-  │
│            │ │   Shape    │ │        │ │  Manager   │ │   Wind     │
└────────────┘ └────────────┘ └────────┘ └────────────┘ └────────────┘

       ┌───────────────────────────┼───────────────────────────┐
       │           │           │   │   │           │           │
       ▼           ▼           ▼       ▼           ▼           ▼
┌────────────┐ ┌────────────┐ ┌────────┐ ┌────────────┐ ┌────────────┐
│  Entity_   │ │   Grid_    │ │ Image- │ │ ImageLayer │ │ Characters │
│  Manager   │ │  Manager   │ │ Layer  │ │ Dithering  │ │            │
└────────────┘ └────────────┘ └────────┘ └────────────┘ └────────────┘

                          ┌─────────────────────┐
                          │ DitherShapeGenerator│
                          └─────────────────────┘

Agents-Liste

Agent Datei Funktion
Background Background.ts Einfarbiger Hintergrund
BackgroundShape BackgroundShape.ts Shape im Zentrum
Brush Brush.ts Universal-Zeichenwerkzeug
ParticleManager Particles.ts Partikel-System
ParticleWind ParticleWind.ts Wind-Partikel mit Noise
Entity_Manager Entities.ts Bouncing/Wrapping Entities
Grid_Manager Grid_Manager.ts Grid-System
ImageLayer ImageLayer.ts Bild-Darstellung
ImageLayerDithering ImageLayerDithering.ts Bild mit Dithering-Effekt
Characters Characters.ts Text/Zeichen-Rendering
DitherShapeGenerator DitherShapeGenerator.ts Shapes aus Dither-Daten

Background

Einfacher farbiger Hintergrund.

Parameter:

Parameter Typ Beschreibung
color string Hintergrundfarbe
opacity number Transparenz

BackgroundShape

Ein Shape zentriert im Hintergrund.

Parameter:

Parameter Typ Beschreibung
brush Brush_ParameterSet Shape-Definition
scale number Skalierung
rotation number Rotation (Grad)

Brush

Das universelle Zeichenwerkzeug.

Parameter:

Parameter Typ Default Beschreibung
shape string 'Circle' Shape-Name
position {x, y} (0.5, 0.5) Position (normalisiert)
size number 100 Größe
rotation number 0 Rotation
fill boolean true Füllung?
fillColor string '#FFFFFFFF' Füllfarbe
border number 0 Rahmenbreite
borderColor string '#000000FF' Rahmenfarbe
opacity number 1 Transparenz

Physics-Optionen:

Option Typ Beschreibung
physics.mode 'none' | 'rigid' | 'soft' Physics-Modus
physics.rigid RigidBodyConfig Rigid Body Settings
physics.soft SoftBodyConfig Soft Body Settings

ParticleManager

Verwaltet Partikel-Systeme.

Parameter:

Parameter Typ Beschreibung
count number Anzahl Partikel
source ParticleSource Spawn-Quelle
physics PhysicsConfig Physics-Einstellungen

Particle Sources:

Source Beschreibung
ImageParticleSource Partikel aus Bild-Pixeln
BrushParticleSource Partikel in Brush-Form

ParticleWind

Wind-Simulation mit Noise.

Parameter:

Parameter Typ Beschreibung
count number Partikel-Anzahl
windStrength number Windstärke
noiseScale number Noise-Skalierung
gravity number Schwerkraft
fadeIn boolean Einblenden?
fadeOut boolean Ausblenden?

Entity_Manager

Bouncing/Wrapping Objekte.

Parameter:

Parameter Typ Beschreibung
count number Anzahl Entities
brush Brush_ParameterSet Entity-Aussehen
velocity {min, max} Geschwindigkeitsbereich
boundaryMode 'bounce' | 'wrap' Grenzverhalten

Entity Features:

  • Position, Velocity, Acceleration
  • Bouncing an Canvas-Grenzen
  • Wrapping (Pac-Man Style)
  • Collision Detection (optional)

Entity Stats Broadcasting

Der Entity_Manager schreibt automatisch Statistiken ins ParameterObject, die von anderen Artworks (z.B. ParameterObserver) empfangen werden können:

// Diese Werte werden automatisch in parameter.entity.stats geschrieben:
{
  centerX: 0.52,      // Normalisiertes Zentrum aller Entities (0-1)
  centerY: 0.48,
  avgSpeed: 0.023,    // Durchschnittsgeschwindigkeit (normalisiert)
  spreadX: 0.31,      // Streuung der Entities
  spreadY: 0.28,
  
  // Positionen der ersten 10 Entities (normalisiert 0-1)
  e0_x: 0.12, e0_y: 0.45,
  e1_x: 0.67, e1_y: 0.23,
  // ... bis e9
}

Anwendung mit ParameterObserver:

// Im Observer-Artwork:
const observer = new ParameterObserver({
  serverUrl: 'http://localhost:4000',
  targetArtwork: 'item-cc-entities',
});

observer.onUpdate((params, artworkId) => {
  const stats = params.entity?.stats;
  if (stats) {
    console.log(`Entities center: (${stats.centerX}, ${stats.centerY})`);
    console.log(`Average speed: ${stats.avgSpeed}`);
  }
});

Mit Smart Filter im ParameterMandala werden genau diese dynamischen Entity-Stats visualisiert, während statische Parameter (Canvas-Size, Animation-Settings) herausgefiltert werden.

Grid_Manager

Dual-View Grid System.

Parameter:

Parameter Typ Beschreibung
cols number Spalten
rows number Zeilen
cellPadding number Zellen-Abstand
showLines boolean Linien zeigen?
showPoints boolean Punkte zeigen?

Views:

  • PointGrid: Fokus auf Kreuzungspunkte und Linien
  • CellGrid: Fokus auf Zellen als Mini-Canvases

ImageLayer

Bild-Darstellung.

Parameter:

Parameter Typ Beschreibung
src string Bild-URL
fit 'contain' | 'cover' | 'fill' Einpassung
position {x, y} Position
opacity number Transparenz

ImageLayerDithering

Bild mit Dithering-Effekt.

Parameter:

Parameter Typ Beschreibung
src string Bild-URL
ditherMode DitherMode Dithering-Algorithmus
cellSize number Zellengröße
shape DitherShape Shape pro Zelle

Dither Modes:

Mode Beschreibung
threshold Einfacher Schwellwert
floydSteinberg Floyd-Steinberg
atkinson Atkinson
ordered Ordered Dithering
halftone Halbton-Muster

Dither Shapes:

Shape Beschreibung
circle Kreise
square Quadrate
line Linien
cross Kreuze
custom Eigene Shapes

Characters

Text und Einzelzeichen.

Parameter:

Parameter Typ Beschreibung
text string Anzuzeigender Text
font string Schriftart
fontSize number Schriftgröße
color string Textfarbe
position {x, y} Position

DitherShapeGenerator

Generiert Shapes aus Dither-Daten für Plotter.

Methoden:

Methode Beschreibung
generate(imageData, opts) Shapes generieren
getShapes() Shape-Array abrufen

Agent-Interface

Alle Agents implementieren:

interface Agent {
  draw(props: ArtworkProps): void;
  update?(deltaTime: number): void;
  setParameter?(key: string, value: any): void;
}

Tweakpane Integration

Jeder Agent hat ensureParameterSet() für Defaults:

// In configure()
Background.ensureParameterSet(parameter, colorset);
ColorSet.ensureParameterSet(parameter, ['palette1', 'palette2']);

Wichtig: ensureParameterSet() muss VOR dem Tweakpane-Check aufgerufen werden (sonst crasht Exhibition Mode).