Actio 5 - Código de la portada

Portada realizada por código Python en Drawbot

Basado en el código creado por Simón Aldana, egresado de la Escuela de Artes Plásticas y Visuales de la Universidad Nacional de Colombia, para la muestra de trabajos finales "Éter Alterado"

let particula = [];
function setup() {
    createCanvas(windowWidth, windowHeight);
    noCursor();
    for (let i = 0; i < 5; i++) {
       particula[i] = new Tesista(random(width), random(height), width / 2);
    }
}
function draw() {
//FONDO
background(30, 30, 30); //RGB
    for (let i = 0; i < 5; i++) {
       particula[i].crearParticula();
       particula[i].moverParticula();
       particula[i].reboteEspacioParticula();
    }
}
class Tesista {
    constructor(x, y, diam) {
    this.posX = x; //posición en el eje X de la figura
    this.posY = y; //posición en el eje Y de la figura
    this.d = diam; //diámetro de la figura
    this.r = 0; //<abajo se explica mejor esta variable>
    this.velX = random(-0.5, 0.5); //velocidad en X de la figura
    this.velY = random(-0.5, 0.5); //velocidad en Y de la figura
    this.resorte = 0.00025; //rebote amortiguado entreparticulas
    this.colorInt = 0; //variable de color particula para degradado -color interno-

    this.colorExt = 0; //variable de color particula para degradado -color externo-
    this.degradado = 0;
    this.cantVertices = 100; //cant. de vertices que componen de la figura -mayor cant mas redondeado-
    this.cantCapas = 9; //cantidad de capas de la figura
    this.contorno = []; //array que contiene los vertices de la figura
    this.cX = []; //array con las posiciones en X de los vertices
    this.cY = []; //array con las posiciones en Y de los vertices
    this.t = random(100); //momento de que se toma como punto de partida del perlin noise del contorno de la figura
    this.inc = 0.0025; //los momentos que le siguen al perlin noise desde el momento inicial "t" -valor pequeño para que sea mas suavizado
    let colorR1 = random(255);
    let colorG1 = random(255);
    let colorB1 = random(50);
    let colorR2 = random(255);
    let colorG2 = random(150);
    let colorB2 = random(50);
    this.colorInt = color(colorR1, colorG1, colorB1, 70);
    this.colorExt = color(colorR2, colorG2, colorB2, 70);
}
crearParticula() {
    this.t += this.inc; //se suceden los momentos del perlin noise
    push();
    for (let capa = 0; capa < this.cantCapas; capa++) {
       let lerpMap = map(capa, 0, this.cantCapas, 0, 1); //mapea la cantidad de capas con valores entre 0 y 1 para que...
       this.degradado = lerpColor(this.colorInt, this.colorExt, lerpMap); //... el nivel de degradado sea el mismo entre una capa y otra
       let s = map(capa, 0, this.cantCapas, this.d * 1.3, 1);
       beginShape();
       for (let j = 0; j < this.cantVertices; j++) {
             let vertice = map(j, 0, this.cantVertices, 0, TWO_PI * 2); //mapea cada vertice a radianes para hacerlos parte de una circunferencia
             this.contorno[j] = vertice; //cada vertice ocupa un lugar en nuestro array del contorno de la figura
             this.cX[j] = cos(vertice);
             this.cY[j] = sin(vertice); //con el seno y el coseno les damos forma de circunferencia
             noiseDetail(1); //suavizar el movimiento de los vertices antes de distorsionar la forma para que se vea redondeada y no poligonal
             this.r = noise(this.cX[j] + this.t, this.cY[j] + this.t, capa + this.t) * s; //distorsionamos la circunferencia gracias a que cada punto de la circunferencia cambia con el perlin noise ("t" e "inc")
             let x = cos(this.contorno[j]) * this.r + this.posX; //cada vertice de la circunferencia
             let y = sin(this.contorno[j]) * this.r + this.posY;
             vertex(x, y);
       }
       endShape(CLOSE);
    }
    pop();
    noStroke();
    fill(this.degradado);
    this.inc = 0.0025;
}
moverParticula() {
    this.posX += this.velX; //desplazamiento en el eje X
    this.posY += this.velY; //desplazamiento en el eje Y
    this.velX = constrain(this.velX, -0.5, 0.5); //restringe la velocidad en X para que no se muevan tan rápido
    this.velY = constrain(this.velY, -0.5, 0.5); //restringe la velocidad en Y para que no se muevan tan rápido
}
reboteEspacioParticula() {
    //rebote con los bordes del espacio
    let minDist = this.d / 2; //distancia mínima a la que puede encontrarse con los bordes
    //con los bordes derecho e inferior
    let dx = width - this.posX; //diferencia del borde derecho con la posición en X de la figura
    let dy = height - this.posY; //diferencia del borde inferior con la posición en Y de la figura
    let angle = atan2(dy, dx); //calcula el angulo en radianes de esas diferencias al origen (0,0)
    if (dx < minDist) {
       let targetX = this.posX + cos(angle) * minDist;
       let ax = (targetX - ((width - 80) - this.d / 2)) * this.resorte; //la aceleración que hace que el rebote sea suavizado gracias al resorte
       this.velX -= ax / 2;
    }
    if (dy < minDist) {
       let targetY = this.posY + sin(angle) * minDist; //la aceleración que hace que el rebote sea suavizado gracias al resorte
       let ay = (targetY - ((height - 80) - this.d / 2)) * this.resorte;
       this.velY -= ay / 2;
    }
    //con los bordes izquierdo y superior
    let dx2 = this.posX; //0 + this.posX ...igual que el anterior pero en ralación al borde izq
    let dy2 = this.posY; //0 + this.posY ...igual que el anterior pero en ralación al borde superior
    let angle2 = atan2(dy2, dx2);
    if (dx2 < minDist) {
       let targetX = this.posX + cos(angle2) * minDist;
       let ax = (targetX - (80 + this.d / 2)) * this.resorte;
       this.velX -= ax / 2;
    }
    if (dy2 < minDist) {
       let targetY = this.posY + sin(angle2) * minDist;
       let ay = (targetY - (80 + this.d / 2)) * this.resorte;
       this.velY -= ay / 2;
       }
    }
}