{"name":"dev_PARTY #015","description":"Interactive NFT by @andriibakulin\n\n<code>\nconst ITEMS_COUNT = 30;\n\nlet gEntities = [];\nlet gSizeArea;\nlet gDistance, gDistanceSqr;\n\n// MagicLogic\n\nclass Entity\n{\n    constructor(seq01, xOffset, yOffset, treeAngle)\n    {\n        this.seq01 = seq01;\n        this.angel = this.seq01 * Math.PI * 2;\n        this.xOffset = xOffset;\n        this.yOffset = yOffset;\n        this.treeAngle = treeAngle;\n\n        this.color = this.seq01 * 255;\n        this.alpha = 255;\n        this.power = new SmoothValue();\n\n        // Dynamic vars\n        this.drawAtX = this.drawAtY = null;\n        this.colorV = null;\n    }\n\n    next(dt)\n    {\n        this.color += dt * 128;\n\n        this.drawAtX = gSizeArea * this.xOffset;\n        this.drawAtY = gSizeArea * this.yOffset;\n        this.colorV  = normalizeColorComp(this.color);\n\n        let dstOffset = 0;\n\n        if (mouseIsPressed)\n        {\n            const dstLengthSqr = (mouseX-this.drawAtX)**2 + (mouseY-this.drawAtY)**2;\n\n            if (dstLengthSqr < gDistanceSqr)\n                dstOffset = Math.sqrt(dstLengthSqr) / gDistance;\n\n            this.alpha = Math.max(this.alpha - dt*1000, 255 * this.power.v * 2, 32);\n            this.alpha = Math.min(this.alpha, 255);\n        }\n        else\n        {\n            if (this.alpha < 255)\n            {\n                this.alpha = this.alpha + dt * 255;\n                this.alpha = Math.min(this.alpha, 255);\n            }\n        }\n\n        if (dstOffset > 0)\n            this.power.update(1 - dstOffset, 2 * dt);\n        else\n            this.power.update(0, 2 * dt);\n    }\n\n    render()\n    {\n        resetMatrix();\n        translate(this.drawAtX, this.drawAtY);\n\n        if (this.power.v > 0)\n            this.drawBranch(0, 0, gSizeArea*0.125*this.power.v, this.angel + 360*this.seq01, 4);\n\n        strokeWeight(8);\n        stroke(this.colorV, 255, 255, this.alpha);\n        point(0,0);\n    }\n\n    drawBranch(x, y, len, dir, depth, level=0)\n    {\n        if (len < 10)\n            return;\n\n        level++;\n        const x2 = x + sin(dir) * len * (this.power.v+0.33);\n        const y2 = y + cos(dir) * len * (this.power.v+0.33);\n\n        strokeWeight(2);\n        stroke(this.colorV, 255, 255, this.alpha * (1 - level/(depth+1)));\n        line(x,y, x2,y2);\n\n        if (level < depth)\n        {\n            this.drawBranch(x2, y2, len * 0.9, dir + this.treeAngle, depth, level);\n            this.drawBranch(x2, y2, len * 0.9, dir - this.treeAngle, depth, level);\n        }\n    }\n}\n\n// Lifecycle\n\nfunction setup()\n{\n    updateConsts();\n    createCanvas(gSizeArea, gSizeArea);\n    background(0);\n\n    pixelDensity(1);\n    frameRate(60);\n    colorMode(HSB, 255);\n    angleMode(DEGREES);\n\n    let count = ITEMS_COUNT;\n    for (let index=0; index<count; index++)\n    {\n        for (let level=0; level<10; level++)\n        {\n            let seq01     = index / count;\n            let radius    = 0.10 + level*0.08;\n            let offsetX   = 0.50 + Math.sin(seq01 * Math.PI * 2) * radius;\n            let offsetY   = 0.50 + Math.cos(seq01 * Math.PI * 2) * radius;\n            let treeAngle = 25*(level+1);\n\n            if (offsetX < 0.0 || offsetY > 1) continue;\n            if (offsetY < 0.0 || offsetY > 1) continue;\n\n            gEntities.push(new Entity(seq01, offsetX, offsetY, treeAngle));\n        }\n    }\n}\n\nfunction windowResized()\n{\n    updateConsts();\n    resizeCanvas(gSizeArea, gSizeArea);\n}\n\nfunction draw()\n{\n    const dt = deltaTime/1000;\n\n    background(0);\n\n    for (const idx in gEntities)\n    {\n        const ent = gEntities[idx];\n        ent.next(dt);\n        ent.render();\n    }\n}\n\n// Helpers\n\nfunction updateConsts()\n{\n    gSizeArea     = Math.min(window.innerWidth, window.innerHeight);\n    gDistance     = gSizeArea / 3;\n    gDistanceSqr  = gDistance ** 2;\n}\n\nfunction normalizeColorComp(v)\n{\n    v %= 256;\n    return v >= 0 ? v : v+256;\n}\n\nfunction clamp(value, min, max)\n{\n    if (value < min) return min;\n    if (value > max) return max;\n    return value;\n}\n\n// Helpers : Smooth\n\nfunction smoothValue(v0, v1, delta)\n{\n    if (v0 === null)\n        return v1;\n\n    const dv = v1 - v0;\n    return Math.abs(dv) <= delta ? v1 : (dv < 0 ? v0 - delta : v0 + delta);\n}\n\nclass SmoothValue\n{\n    constructor(v=null)\n    {\n        this.v = v;\n    }\n\n    update(v, delta)\n    {\n        this.v = smoothValue(this.v, v, delta);\n    }\n}\n</code>","tags":["genart","codeart","interactive","procedural","generative","realtime","abstract","colorful","art","algorithmic","script","p5js","js","hen500k"],"symbol":"OBJKT","artifactUri":"ipfs://QmeewFy64q3S16xEiKxHM1Xcm6TV2XnuEpvfsnYy3TyMzq","displayUri":"ipfs://QmW23EEdoWt8FZywZsLWFHofxPUKduGj1q9RSbibA12RW9","thumbnailUri":"ipfs://QmNrhZHUaEqxhyLfqoq1mtHSipkWHeT31LNHb1QEbDHgnc","creators":["tz1Ys42frYhgxHxXtqoY42GiuRPZ9ykbP86Y"],"formats":[{"uri":"ipfs://QmeewFy64q3S16xEiKxHM1Xcm6TV2XnuEpvfsnYy3TyMzq","mimeType":"application/x-directory"}],"decimals":0,"isBooleanAmount":false,"shouldPreferSymbol":false}