xxxxxxxxxx
195
let size = 320; // Size of the canvas in px
let d = 8; // Diameter of the circles in px
let r = d / 2; //Radius of the circles in px
let squares; // Number of squares
let xoff, yoff, zoff; // Offsets for the noise function
let xyIncrement = 0.1; // This is like the zoom, lower values increment the zoom, higher values decrement the zoom
let zIncrement = 0.008; // And this is like the velocity at which the circles change color, low values give low velocity, high values give high velocity
let field = []; // Noise field
let buttonLoop, buttonColors; // Buttons
let doLoop = true,
showCircles = true;
function setup() {
setButtons();
createCanvas(size, size);
colorMode(HSB); // For rainbow colors
squares = width / d;
zoff = random(100);
// Fill the field to have a 2D array
for (let i = 0; i <= squares; i++) {
let row = [];
for (let j = 0; j <= squares; j++) {
row.push(-1);
}
field.push(row);
}
}
function setButtons(){
// Colors button
buttonColors = document.getElementById("colors-btn");
buttonColors.addEventListener("click", changeShowColors);
buttonColors.value= "B&W";
// Loop button
buttonLoop = document.getElementById("pause-btn");
buttonLoop.addEventListener("click", changeDoLoop);
buttonLoop.value= "Pause";
}
function draw() {
if (doLoop) {
background(0);
noiseField();
for (let i = 0; i < squares; i++) {
for (let j = 0; j < squares; j++) {
updateLines(i, j);
}
}
}
}
function noiseField() {
xoff = 0;
for (let i = 0; i <= squares; i++) {
yoff = 0;
for (let j = 0; j <= squares; j++) {
field[i][j] = noise(xoff, yoff, zoff);
if(showCircles){
drawCircle(i, j);
}
yoff += xyIncrement;
}
xoff += xyIncrement;
}
zoff += zIncrement;
}
function drawCircle(row, col) {
let noiseValue = field[row][col];
push();
/* noiseValue < 0.5 then hue goes from 0 to 360
noiseValue >= 0.5 then hue goes from 0 to 360 again
If I just map noiseValue from 0 to 360 there would be too little colors, this way looks prettier
*/
if (noiseValue < 0.5) {
fill(noiseValue * 720, // Multiplying by 720 is easier and faster than using the map function
255,
255);
} else {
fill(noiseValue * 720 - 360, // Same here
255,
255);
}
noStroke();
circle(row * d, col * d, d);
pop();
}
function updateLines(i, j) {
let p = {
"a": getPoint(i, j, "a"), // Top
"b": getPoint(i, j, "b"), // Right
"c": getPoint(i, j, "c"), // Bottom
"d": getPoint(i, j, "d"), // Left
"mid": getPoint(i, j, "mid") // Center
};
let stateValue = round(field[i][j]) * 1 + //Top left
round(field[i][j + 1]) * 2 + //Top right
round(field[i + 1][j + 1]) * 4 + //Bottom right
round(field[i + 1][j]) * 8; //Bottom left
switch(stateValue){
case 1:
case 14:
drawLine(p.d, p.mid);
drawLine(p.mid, p.a);
break;
case 2:
case 13:
drawLine(p.a, p.mid);
drawLine(p.mid, p.b);
break;
case 3:
case 12:
drawLine(p.d, p.b);
break;
case 4:
case 11:
drawLine(p.b, p.mid);
drawLine(p.mid, p.c);
break;
case 5:
case 10:
drawLine(p.d, p.b);
drawLine(p.a, p.c);
break;
case 6:
case 9:
drawLine(p.a, p.c);
break;
case 7:
case 8:
drawLine(p.c, p.mid);
drawLine(p.mid, p.d);
break;
}
}
function getPoint(i, j, name) {
switch (name) {
case "a": // Top
return createVector(i * d , j * d + r);
case "b": // Right
return createVector(i * d + r, j * d + d);
case "c": // Bottom
return createVector(i * d + d, j * d + r);
case "d": // Left
return createVector(i * d + r, j * d );
case "mid":
return createVector(i * d + r, j * d + r);
}
}
function drawLine(p1, p2) {
push();
strokeWeight(2);
stroke(0, 0, 255); // White in HSB
noFill();
line(p1.x, p1.y, p2.x, p2.y);
pop();
}
function changeDoLoop() {
doLoop = !doLoop;
if(doLoop){
buttonLoop.value = "Pause";
}else{
buttonLoop.value = "Play";
}
}
function changeShowColors() {
showCircles = !showCircles;
if(showCircles){
buttonColors.value = "B&W";
}else{
buttonColors.value = "Colors";
}
}