98 lines, no comments ยท 1,162 tokens, written in 19 seconds for $0.012


 1  let particles = [];
 2  let paletteIndex = 0;
 3  let time = 0;
 4  
 5  const palettes = [
 6    [[70, 240, 220], [80, 140, 255], [190, 100, 255]],
 7    [[255, 100, 130], [255, 175, 80], [255, 225, 150]],
 8    [[130, 255, 170], [40, 200, 220], [220, 255, 130]]
 9  ];
10  
11  function setup() {
12    createCanvas(windowWidth, windowHeight);
13    pixelDensity(1);
14    strokeWeight(1.2);
15    resetParticles();
16  }
17  
18  function resetParticles() {
19    background(5, 8, 20);
20    const count = min(1500, floor(width * height / 650));
21    particles = Array.from({ length: max(250, count) }, () => ({
22      x: random(width),
23      y: random(height),
24      vx: 0,
25      vy: 0,
26      speed: random(0.8, 2.6),
27      colorIndex: floor(random(3)),
28      life: random(100, 500)
29    }));
30  }
31  
32  function draw() {
33    blendMode(BLEND);
34    background(5, 8, 20, 17);
35    blendMode(ADD);
36  
37    const palette = palettes[paletteIndex];
38    const pointerActive = mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height;
39  
40    for (const p of particles) {
41      const oldX = p.x;
42      const oldY = p.y;
43      const angle = noise(p.x * 0.0025, p.y * 0.0025, time) * TWO_PI * 3;
44      let fx = cos(angle);
45      let fy = sin(angle);
46  
47      if (pointerActive) {
48        const dx = p.x - mouseX;
49        const dy = p.y - mouseY;
50        const distance = sqrt(dx * dx + dy * dy);
51        if (distance > 1 && distance < 220) {
52          const force = (1 - distance / 220) * 3;
53          fx += (-dy / distance + dx / distance * 0.25) * force;
54          fy += (dx / distance + dy / distance * 0.25) * force;
55        }
56      }
57  
58      p.vx = lerp(p.vx, fx * p.speed, 0.075);
59      p.vy = lerp(p.vy, fy * p.speed, 0.075);
60      p.x += p.vx;
61      p.y += p.vy;
62      p.life--;
63  
64      if (p.x < 0 || p.x > width || p.y < 0 || p.y > height || p.life <= 0) {
65        p.x = random(width);
66        p.y = random(height);
67        p.vx = 0;
68        p.vy = 0;
69        p.life = random(150, 550);
70        continue;
71      }
72  
73      const c = palette[p.colorIndex];
74      const alpha = min(65, p.life * 3);
75      stroke(c[0], c[1], c[2], alpha);
76      line(oldX, oldY, p.x, p.y);
77    }
78  
79    blendMode(BLEND);
80    time += 0.0015;
81  }
82  
83  function mousePressed() {
84    paletteIndex = (paletteIndex + 1) % palettes.length;
85  }
86  
87  function keyPressed() {
88    if (key === ' ') {
89      resetParticles();
90      return false;
91    }
92  }
93  
94  function windowResized() {
95    resizeCanvas(windowWidth, windowHeight);
96    resetParticles();
97  }
98