{"name":"dev_PARTY #006","description":"Interactive NFT by @andriibakulin\n\n<code>\nlet gNullColor;\n\nlet gPoints = [];\nlet gLines = [];\n\nlet gDistanceRange, gDistanceRangeSqr;\n\nclass EntityPoint\n{\n    constructor(index)\n    {\n        this.index = index;\n\n        this.x = Math.random() * window.innerWidth;\n        this.y = Math.random() * window.innerHeight;\n        this.x_offset = 0;\n        this.y_offset = 0;\n        this.x_last_draw = this.x;\n        this.y_last_draw = this.y;\n\n        const c = Math.random();\n        this.color_base = color(c * 255, 255, 255);\n        this.color_line = color(c * 255, 255, 255);\n        this.color_back = color(c * 255, 255, 255, 111);\n\n        this.offset = Math.random() * 123;\n        this.speed  = 0.5 + Math.random() * 4.5 * (Math.random() < 0.5 ? -1 : +1);\n        this.radius = 1.0 + Math.random() * 29;\n\n        this.activeForce = 0;\n    }\n\n    getX()\n    {\n        return this.x + this.x_offset;\n    }\n\n    getY()\n    {\n        return this.y + this.y_offset;\n    }\n\n    next(dt)\n    {\n        this.offset += dt * this.speed * (1 + this.activeForce);\n        this.x_offset = Math.sin(this.offset) * this.radius;\n        this.y_offset = Math.cos(this.offset) * this.radius;\n    }\n\n    distanceSqr(x, y)\n    {\n        return (x - this.getX())**2 + (y - this.getY())**2;\n    }\n}\n\nclass EntityLine\n{\n    constructor(p1, p2)\n    {\n        this.p1 = p1;\n        this.p2 = p2;\n        this.w  = Math.random() < 0.5 ? 1 : 2;\n\n        this.v = 0;\n        this.t = Math.random() * 3 + 1;\n    }\n\n    next(dt)\n    {\n        this.v += dt;\n        return this.v < this.t;\n    }\n\n    render()\n    {\n        let t0 = this.v/this.t;\n        let t1 = t0 * 2;\n\n        if (t1 > 1)\n            t1 = 2 - t1;\n\n        let col = lerpColor(this.p1.color_line, this.p2.color_line, t0);\n\n        strokeWeight(this.w);\n        stroke(lerpColor(gNullColor, col, t1));\n\n        line(\n            this.p1.x_last_draw, this.p1.y_last_draw,\n            this.p2.x_last_draw, this.p2.y_last_draw);\n    }\n}\n\nfunction setup()\n{\n    gNullColor = color(0,0,0,0);\n\n    createCanvas(window.innerWidth, window.innerHeight)\n\n    pixelDensity(1);\n    frameRate(60);\n\n    angleMode(DEGREES);\n\n    setupWorkingAreaAndData();\n}\n\nfunction windowResized()\n{\n    resizeCanvas(window.innerWidth, window.innerHeight);\n\n    setupWorkingAreaAndData();\n}\n\nfunction setupWorkingAreaAndData()\n{\n    gDistanceRange    = Math.min(window.innerWidth, window.innerHeight)*0.33;\n    gDistanceRangeSqr = gDistanceRange ** 2;\n\n    background(0);\n\n    gPoints = [];\n    gLines = [];\n\n    colorMode(HSB, 255);\n    for (let index=0; index<30; index++)\n    {\n        gPoints.push(new EntityPoint(index));\n    }\n    colorMode(RGB, 255);\n}\n\nfunction draw()\n{\n    const dt = deltaTime/1000;\n\n    background(0);\n\n    if (gLines.length < 16)\n    {\n        const p1 = gPoints[floor(Math.random()*gPoints.length)];\n        const p2 = gPoints[floor(Math.random()*gPoints.length)];\n        gLines.push(new EntityLine(p1, p2));\n    }\n\n    for (const idx in gLines)\n    {\n        const line = gLines[idx];\n\n        if (line.next(dt))\n            line.render();\n        else\n            gLines.splice(idx, 1);\n    }\n\n    for (const idx in gPoints)\n    {\n        const point = gPoints[idx];\n        point.next(dt);\n\n        let point_x = point.getX();\n        let point_y = point.getY();\n        let point_s = 5;\n\n        if (mouseIsPressed)\n        {\n            const entDistanceSqr = point.distanceSqr(mouseX, mouseY);\n\n            if (entDistanceSqr < gDistanceRangeSqr)\n            {\n                const entDistance = Math.sqrt(entDistanceSqr);\n                const dst = entDistance / gDistanceRange;\n                const frc = 1 - dst;\n\n                point.activeForce = frc;\n\n                point_x = lerp(point_x, mouseX, frc);\n                point_y = lerp(point_y, mouseY, frc);\n\n                const dx = point_x - mouseX;\n                const dy = point_y - mouseY;\n\n                noStroke();\n                fill(lerpColor(point.color_back, color(0,0,0,0), dst));\n\n                circle(\n                    point_x - dx * dst * 3,\n                    point_y - dy * dst * 3,\n                    gDistanceRange * (point.radius/10) * frc);\n\n                point_s *= (frc + 1)**2;\n            }\n        }\n        else\n        {\n            point.activeForce = 0;\n        }\n\n        noStroke();\n        fill(point.color_base);\n        circle(point_x, point_y, point_s);\n\n        point.x_last_draw = point_x;\n        point.y_last_draw = point_y;\n    }\n}\n</code>","tags":["codeart","interactive","procedural","generative","generativeart","realtime","p5js","p5func"],"symbol":"OBJKT","artifactUri":"ipfs://QmcP1RndAvYWEwmS8oPZn4uEXQMFXdhpRoJwwAEdoeJ2HV","displayUri":"ipfs://Qme1np4JEwMZUXKjQnxsDmvxZULDjpzds7syJ27QCg57oC","thumbnailUri":"ipfs://QmNrhZHUaEqxhyLfqoq1mtHSipkWHeT31LNHb1QEbDHgnc","creators":["tz1Ys42frYhgxHxXtqoY42GiuRPZ9ykbP86Y"],"formats":[{"uri":"ipfs://QmcP1RndAvYWEwmS8oPZn4uEXQMFXdhpRoJwwAEdoeJ2HV","mimeType":"application/x-directory"}],"decimals":0,"isBooleanAmount":false,"shouldPreferSymbol":false}