2020 | P5
A p5 sketch of an optionally interactive automatic drawing generator. It generates a unique pattern using black lines, and you can also move over your mouse to add some red color. Old colors slowly fade over time. See and fork it at p5.js editor here.
This set of code is based on what I learned with a tutorial Coding Challenge #24: Perlin Noise Flow Field by amazing Daniel Shiffman at The Coding Train.
var inc = 0.1;
var scl = 40;
var cols, rows;
var zoff = 0;
var particles = [];
var flowfield;
var whiteScreen;
var clothfillColor;
var start = 200;
function setup() {
createCanvas(700, 700);
cols = floor(width / scl);
rows = floor(height / scl);
flowfield = new Array(cols * rows);
for (var i = 0; i < 400; i++) {
particles[i] = new Particle();
}
whiteScreen = color(210,180,170,0.5);
clothfillColor = color(130, 30, 35, 5);
background(210,180,170);
}
function draw() {
background(whiteScreen);
var yoff = 0;
for (var y = 0; y < rows; y++) {
var xoff = 0;
for (var x = 0; x < cols; x++) {
var index = x + y * cols;
var angle = noise(xoff, yoff, zoff) * TWO_PI * 4;
var v = p5.Vector.fromAngle(angle);
v.setMag(0.1);
flowfield[index] = v;
xoff += inc;
// stroke(0, 50);
// push();
// translate(x*scl, y*scl);
// rotate(v.heading());
// strokeWeight(1);
// line(0,0,scl,0);
// pop();
}
yoff += inc;
zoff += 0.0002
}
for (var i = 0; i < particles.length; i++) {
particles[i].follow(flowfield);
particles[i].update();
particles[i].edges();
particles[i].show();
}
}
function mouseMoved() {
fill(clothfillColor);
noStroke();
beginShape();
var clothyoff = mouseY + noise(start);
for (var clothy = -10; clothy < 10; clothy++) {
var clothx = noise(clothyoff) * mouseX * 2;
vertex(clothx + clothy, clothyoff + clothy);
clothyoff += inc * 1.2;
}
endShape(CLOSE);
start += inc;
}
function Particle() {
this.pos = createVector(random(width), random(height));
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.maxspeed = 2;
this.prevPos = this.pos.copy();
this.update = function() {
this.vel.add(this.acc);
this.vel.limit(this.maxspeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
this.follow = function(vectors) {
var x = floor(this.pos.x / scl);
var y = floor(this.pos.y / scl);
var index = x + y * cols;
var force = vectors[index];
this.applyForce(force);
}
this.applyForce = function(force) {
this.acc.add(force);
}
this.show = function() {
stroke(0, 7);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.updatePrev = function() {
this.prevPos.x = this.pos.x;
this.prevPos.y = this.pos.y;
}
this.edges = function() {
if (this.pos.x > width) {
this.pos.x = 0;
this.updatePrev();
}
if (this.pos.x < 0) {
this.pos.x = width;
this.updatePrev();
}
if (this.pos.y > height) {
this.pos.y = 0;
this.updatePrev();
}
if (this.pos.y < 0) {
this.pos.y = height;
this.updatePrev();
}
}
}