Source of: Nebula Drift, by Grok 4.7
79 lines, no comments ยท 1,104 tokens, written in 11 seconds for $0.0075
1 let particles = [];
2 let hueBase = 200;
3
4 function setup() {
5 createCanvas(windowWidth, windowHeight);
6 colorMode(HSB, 360, 100, 100, 100);
7 background(230, 40, 6);
8 const n = Math.min(280, Math.floor((width * height) / 8000));
9 for (let i = 0; i < n; i++) {
10 particles.push(spawnParticle(random(width), random(height)));
11 }
12 }
13
14 function spawnParticle(x, y) {
15 const ang = random(TWO_PI);
16 const spd = random(0.4, 1.8);
17 return {
18 x,
19 y,
20 vx: cos(ang) * spd,
21 vy: sin(ang) * spd,
22 r: random(1.2, 3.4),
23 hue: random(160, 320),
24 life: random(80, 240)
25 };
26 }
27
28 function draw() {
29 noStroke();
30 fill(230, 45, 5, 12);
31 rect(0, 0, width, height);
32
33 hueBase = (hueBase + 0.15) % 360;
34 const cx = width * 0.5 + cos(frameCount * 0.004) * width * 0.08;
35 const cy = height * 0.5 + sin(frameCount * 0.003) * height * 0.06;
36
37 for (let i = 0; i < particles.length; i++) {
38 const p = particles[i];
39 const dx = cx - p.x;
40 const dy = cy - p.y;
41 const d = max(12, sqrt(dx * dx + dy * dy));
42 p.vx += (dx / d) * 0.035;
43 p.vy += (dy / d) * 0.035;
44
45 const mx = mouseX - p.x;
46 const my = mouseY - p.y;
47 const md = sqrt(mx * mx + my * my);
48 if (md < 180 && md > 1) {
49 const pull = (1 - md / 180) * 0.45;
50 p.vx += (mx / md) * pull;
51 p.vy += (my / md) * pull;
52 }
53
54 p.vx += cos(frameCount * 0.01 + p.hue) * 0.02;
55 p.vy += sin(frameCount * 0.008 + i) * 0.02;
56 p.vx *= 0.985;
57 p.vy *= 0.985;
58 p.x += p.vx;
59 p.y += p.vy;
60 p.life -= 1;
61
62 if (p.x < -20 || p.x > width + 20 || p.y < -20 || p.y > height + 20 || p.life <= 0) {
63 particles[i] = spawnParticle(random(width), random(height));
64 continue;
65 }
66
67 const h = (p.hue + hueBase * 0.25) % 360;
68 fill(h, 70, 100, 70);
69 circle(p.x, p.y, p.r * 2);
70 fill(h, 40, 100, 18);
71 circle(p.x, p.y, p.r * 8);
72 }
73 }
74
75 function windowResized() {
76 resizeCanvas(windowWidth, windowHeight);
77 background(230, 40, 6);
78 }
79