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; } } }