let drawBowlLoopCount = 1;
let baseLineThickness = 1;
let leafNoiseScale = 0.01;
createCanvas(windowWidth, windowHeight);
describe("This artwork draws inspiration from potted succulent plants found on the streets. It integrates recursive algorithms to make the layout and uses easing functions to create the leaf shapes.");
pixelDensity(drawDensity);
dotDensity = random(0.05, 0.3);
lineDensity = random(0.4, 0.8);
noiseScaleX = random(0.0001, 0.01);
noiseScaleY = random(0.0001, 0.01);
baseLineThickness = random(1, 6);
baseLineLength = random(6, 12);
mainHue = random(0, 360);
curveTypes.push(easeOutSine);
curveTypes.push(easeOutCubic);
curveTypes.push(easeOutQuart);
curveTypes.push(easeOutQuint);
curveTypes.push(easeOutExpo);
curveTypes.push(easeInOutSine);
curveTypes.push(easeInOutBounce);
curveTypes.push(easeOutBounce);
curveTypes.push(easeOutElastic);
curveTypes.push(easeInSine);
curveTypes.push(easeOutBack);
let bgHueA = processHue(mainHue + random(-10, 10));
let bgHueB = processHue(mainHue + random(-10, 10));
let bgSatA = random(0, 20);
let bgSatB = random(0, 20);
let bgBriA = random(5, 25);
let bgBriB = random(5, 25);
let bgLineCount = height * lineDensity;
let lastDotDensity = dotDensity;
for (let y = 0; y < bgLineCount; y++) {
let t = y / (bgLineCount - 1);
NYSetColorLerp(bgHueA, bgSatA, bgBriA, bgHueB, bgSatB, bgBriB, t);
NYDotLine(0, nowY, width, nowY);
dotDensity = lastDotDensity;
let xCount = floor(random(1, 3));
let yCount = floor(random(1, 3));
let padding = min(width, height) * paddingRatio;
let rectWidth = (width - 2 * padding) / xCount;
let rectHeight = (height - 2 * padding) / yCount;
for (let x = 0; x < xCount; x++) {
for (let y = 0; y < yCount; y++) {
let startX = rectWidth * x + padding;
let startY = rectHeight * y + padding;
let plantX = startX + random(rectWidth * 0.2, rectWidth * 0.8);
let plantY = startY + random(rectHeight * 0.2, rectHeight * 0.8);
let plantSize = min(rectWidth, rectHeight) * random(0.3, 0.6);
let leafWidth = plantSize * random(0.2, 0.8);
let layers = floor(random(3, 12));
let countPerLayer = floor(random(3, 24));
let rects = SubdivideRect(startX, startY, rectWidth, rectHeight, 0);
for (let r = 0; r < rects.length; r++) {
let bowlWidth = rectObj.w;
let bowlHeight = rectObj.h;
let newBowl = new PlantBowl(bowlX, bowlY, bowlWidth, bowlHeight);
for (let i = 0; i < bowls.length; i++) {
if (bowls[i].bowlType == 3)
if (bowls[i].bowlType <= 1)
await bowls[i].drawBowlRect();
else if (bowls[i].bowlType == 2)
await bowls[i].drawBowlRound();
bowls.sort(function (a, b) {
if (a.plantSize < b.plantSize)
else if (a.plantSize > b.plantSize)
for (let i = 0; i < bowls.length; i++) {
if (bowls[i].bowlType == 3)
function SubdivideRect(_x, _y, _width, _height, _depth) {
let doSplit = random(0, 1) < 0.9;
if (min(_width, _height) < 120) {
let splitRatio = random(0.4, 0.6);
let rectA_width = _width * splitRatio;
let rectA_height = _height;
let rectB_x = _x + _width * splitRatio;
let rectB_width = _width * (1 - splitRatio);
let rectB_height = _height;
let rectA = SubdivideRect(rectA_x, rectA_y, rectA_width, rectA_height, _depth + 1);
let rectB = SubdivideRect(rectB_x, rectB_y, rectB_width, rectB_height, _depth + 1);
return rectA.concat(rectB);
let rectA_width = _width;
let rectA_height = _height * splitRatio;
let rectB_y = _y + _height * splitRatio;
let rectB_width = _width;
let rectB_height = _height * (1 - splitRatio);
let rectA = SubdivideRect(rectA_x, rectA_y, rectA_width, rectA_height, _depth + 1);
let rectB = SubdivideRect(rectB_x, rectB_y, rectB_width, rectB_height, _depth + 1);
return rectA.concat(rectB);
return [{ x: _x, y: _y, w: _width, h: _height, depth: _depth }];
return new Promise(resolve => setTimeout(resolve, ms));
saveCanvas(`succulent-${width}-${height}-${fxhash}.png`);