// — Sensory Studio: círculos -> partículas -> texto — // p5.js sketch // Requiere una fuente TTF/OTF accesible (usa la que ya tienes en tu proyecto) let font; // fuente para textToPoints let targetPoints = []; // puntos que dibujan “sensory studio” let particles = []; // partículas que viajan a los puntos destino let animationStarted = false; let built = false; const TEXT = “sensory studio”; // <- el texto final const SAMPLE = 0.3; // densidad de puntos del texto (0.1–0.5) const TEXT_SIZE_RATIO = 0.18; // tamaño del texto relativo al ancho // ---- Utilidades Bézier (tus funciones adaptadas) ---- function myBezierPoint(p0, p1, p2, p3, t) { const u = 1 - t; return u*u*u*p0 + 3*u*u*t*p1 + 3*u*t*t*p2 + t*t*t*p3; } function myBezierTangent(p0, p1, p2, p3, t) { const u = 1 - t; return 3*u*u*(p1 - p0) + 6*u*t*(p2 - p1) + 3*t*t*(p3 - p2); } function myBezierPath(start, end, a1, a2, L1=100, L2=100, steps=120) { const points = []; const {x:x0,y:y0} = start, {x:x3,y:y3} = end; const x1 = x0 + L1 * Math.cos(a1); const y1 = y0 + L1 * Math.sin(a1); const x2 = x3 - L2 * Math.cos(a2); const y2 = y3 - L2 * Math.sin(a2); for (let i=0;i<=steps;i++){ const t = i/steps; const x = myBezierPoint(x0,x1,x2,x3,t); const y = myBezierPoint(y0,y1,y2,y3,t); const dx = myBezierTangent(x0,x1,x2,x3,t); const dy = myBezierTangent(y0,y1,y2,y3,t); const a = Math.atan2(dy,dx); points.push({x,y,a}); } return points; } // ---- Partícula ---- class Particle { constructor(x, y, r=4){ this.x = x; this.y = y; this.r = r; this.baseR = r; this.col = color(255); this.jitterPhase = random(1000); this.targetIndex = -1; // índice dentro de targetPoints this.curve = null; // ruta (array de puntos) this.i = 0; // índice de avance en la curva this.iMax = 1; this.wait = floor(random(10,60)); // pequeño retardo entre partículas } setTarget(targetPt, angleOut=0, angleIn=0){ // genera ruta curva desde (x,y) hasta (targetPt) const L = random(width*0.06, width*0.12); const steps = floor(random(90, 160)); this.curve = myBezierPath( {x:this.x, y:this.y}, {x:targetPt.x, y:targetPt.y}, angleOut, angleIn, L, L, steps ); this.i = 0; this.iMax = this.curve.length-1; } idle() { // pequeña animación de respiración/jitter mientras son “círculos” const t = frameCount*0.02 + this.jitterPhase; const jx = noise(t)*2 - 1; const jy = noise(t+999)*2 - 1; push(); noStroke(); fill(255, 255, 255, 200); circle(this.x + jx*2, this.y + jy*2, this.r*2); pop(); } fly() { if (!this.curve) return; if (this.wait > 0) { this.wait–; this.idle(); return; } // avanza const speed = 1.5; // controla la rapidez a lo largo de la curva this.i = min(this.i + speed, this.iMax); // suaviza el radio (de círculo grande a partícula pequeña) this.r = lerp(this.r, this.baseR*0.6, 0.15); const p = this.curve[floor(this.i)]; this.x = p.x; this.y = p.y; // dibuja una estela sutil push(); noFill(); stroke(255, 80); strokeWeight(1); point(this.x, this.y); pop(); // partícula push(); noStroke(); fill(255); circle(this.x, this.y, this.r*2); pop(); } atTarget() { return !!this.curve && this.i >= this.iMax; } } function preload(){ // Usa una fuente que tengas en tu proyecto: // Ejemplos de tu código original: “PermanentMarker-Regular.ttf” o “Stick-Regular.ttf” font = loadFont(“PermanentMarker-Regular.ttf”); } function setup(){ createCanvas(windowWidth, windowHeight); pixelDensity(1); textFont(font); // 1) construir puntos objetivo para “sensory studio” const textSizePx = width * TEXT_SIZE_RATIO; const marginTop = height*0.5; // luego recentramos verticalmente const marginLeft = width*0.08; const bounds = font.textBounds(TEXT, marginLeft, marginTop, textSizePx); // centrado const offsetX = (width – bounds.w) * 0.5 – bounds.x; const offsetY = (height – bounds.h) * 0.5 – bounds.y; targetPoints = font.textToPoints(TEXT, marginLeft + offsetX, marginTop + offsetY, textSizePx, { sampleFactor: SAMPLE, simplifyThreshold: 0 }); // 2) crear “círculos grandes” como fuentes de partículas // distribuimos partículas iniciales en varios anillos concéntricos const total = targetPoints.length; const rings = 3; const center = createVector(width*0.5, height*0.55); const maxR = min(width, height) * 0.32; const ringCounts = []; let acc = 0; for (let k=0; k
Sensory Circle
A monthly encounter with the invisible. From anywhere in the world.
Join Sensory Circle — an intimate and living archive of sensorial creation. Each month you will receive an exclusive poetic experience: a sound, a story, a gesture, or a visual piece. You will also gain access to collective sessions and creative material in development.
- • 1 sensory piece per month (audio, image, poetic text or micro-performance)
- • Insights and fragments from creative processes
- • Invitations to virtual encounters
- • Special discounts for Sensory Studio experiences
For only 2 € per month, support our independent creation and become part of a global circle of perception and imagination.
*You’ll receive a monthly email with your sensory content. Cancel anytime.
