67 lines, 6 of them comments ยท 1,057 tokens, written in 7 seconds for $0.0087


 1  let particles = [];
 2  const NUM = 600;
 3  
 4  function setup() {
 5    createCanvas(windowWidth, windowHeight);
 6    colorMode(HSB, 360, 100, 100, 100);
 7    noStroke();
 8    for (let i = 0; i < NUM; i++) {
 9      particles.push(new Orb());
10    }
11    background(0);
12  }
13  
14  function draw() {
15    // Translucent background for motion blur
16    fill(0, 0, 0, 10);
17    rect(0, 0, width, height);
18    translate(width / 2, height / 2);
19    for (let p of particles) {
20      p.update();
21      p.show();
22    }
23  }
24  
25  class Orb {
26    constructor() {
27      this.angle = random(TWO_PI);
28      this.baseR = random(50, min(width, height) * 0.45);
29      this.r = this.baseR;
30      this.speed = random(0.002, 0.01) * (random() < 0.5 ? 1 : -1);
31      this.hue = map(this.baseR, 50, min(width, height) * 0.45, 180, 360);
32    }
33  
34    update() {
35      // Natural orbit
36      this.angle += this.speed;
37  
38      // Mouse interaction (repulsion)
39      let mx = mouseX - width / 2;
40      let my = mouseY - height / 2;
41      let px = cos(this.angle) * this.r;
42      let py = sin(this.angle) * this.r;
43      let d = dist(mx, my, px, py);
44      if (d < 120) {
45        // Push outward proportionally
46        this.r += (120 - d) * 0.3;
47      }
48  
49      // Ease radius back toward base radius
50      this.r = lerp(this.r, this.baseR, 0.02);
51    }
52  
53    show() {
54      let x = cos(this.angle) * this.r;
55      let y = sin(this.angle) * this.r;
56      fill((this.hue + frameCount * 0.3) % 360, 80, 100, 80);
57      ellipse(x, y, 4, 4);
58    }
59  }
60  
61  function windowResized() {
62    resizeCanvas(windowWidth, windowHeight);
63    // Recalculate base radius range for particles
64    for (let p of particles) {
65      p.baseR = constrain(p.baseR, 50, min(width, height) * 0.45);
66    }
67  }