Source of: Aurora Flow Field, by GPT-5
177 lines, 2 of them comments ยท 5,864 tokens, written in 81 seconds for $0.059
1 let particles = [];
2 let numParticles;
3 let noiseScale = 0.0015;
4 let zOff = 0;
5 let zInc = 0.002;
6 let speed = 1.2;
7 let hueShift = 0;
8 let hueInc = 0.1;
9 let fadeAlpha = 0.08; // 0..1
10 let paused = false;
11 let showHUD = true;
12 let mode = 0; // color mode
13 let seedVal;
14
15 class Particle {
16 constructor() {
17 this.reset(true);
18 }
19 reset(randomPos = false) {
20 if (randomPos) {
21 this.pos = createVector(random(width), random(height));
22 } else {
23 let side = floor(random(4));
24 if (side === 0) this.pos = createVector(random(width), -1);
25 else if (side === 1) this.pos = createVector(width + 1, random(height));
26 else if (side === 2) this.pos = createVector(random(width), height + 1);
27 else this.pos = createVector(-1, random(height));
28 }
29 this.prev = this.pos.copy();
30 this.hueOff = random(360);
31 }
32 update() {
33 let nx = this.pos.x * noiseScale;
34 let ny = this.pos.y * noiseScale;
35 let angle = noise(nx, ny, zOff) * TWO_PI * 4.0;
36 let v = p5.Vector.fromAngle(angle);
37 v.mult(speed);
38 this.pos.add(v);
39
40 if (
41 this.pos.x < -2 ||
42 this.pos.x > width + 2 ||
43 this.pos.y < -2 ||
44 this.pos.y > height + 2
45 ) {
46 this.reset(false);
47 this.prev = this.pos.copy();
48 }
49 }
50 draw() {
51 let h;
52 if (mode === 0) {
53 h = (hueShift + this.hueOff) % 360;
54 } else if (mode === 1) {
55 h = map(this.pos.x, 0, width, 0, 360);
56 } else if (mode === 2) {
57 let nx = this.pos.x * noiseScale;
58 let ny = this.pos.y * noiseScale;
59 let a = (noise(nx, ny, zOff) * 360 * 4.0) % 360;
60 h = a;
61 } else {
62 let d = dist(this.pos.x, this.pos.y, mouseX, mouseY);
63 h = map(d, 0, max(width, height), 200, 360) % 360;
64 }
65 stroke(h, 80, 100, 0.5);
66 strokeWeight(1);
67 line(this.prev.x, this.prev.y, this.pos.x, this.pos.y);
68 this.prev.set(this.pos);
69 }
70 }
71
72 function setup() {
73 createCanvas(windowWidth, windowHeight);
74 pixelDensity(1);
75 colorMode(HSB, 360, 100, 100, 1);
76 background(0);
77 init();
78 }
79
80 function init() {
81 seedVal = floor(random(1e9));
82 randomSeed(seedVal);
83 noiseSeed(seedVal);
84 particles = [];
85 numParticles = floor((width * height) / 2200);
86 numParticles = constrain(numParticles, 400, 2500);
87 for (let i = 0; i < numParticles; i++) {
88 particles.push(new Particle());
89 }
90 }
91
92 function draw() {
93 if (paused) {
94 drawHUD();
95 return;
96 }
97
98 if (fadeAlpha > 0) {
99 noStroke();
100 fill(0, 0, 0, fadeAlpha);
101 rect(0, 0, width, height);
102 }
103
104 zOff += zInc;
105 hueShift = (hueShift + hueInc) % 360;
106
107 if (mouseIsPressed) {
108 let mx = mouseX * noiseScale;
109 let my = mouseY * noiseScale;
110 zOff += 0.004 * sin(frameCount * 0.05 + noise(mx, my) * TWO_PI);
111 }
112
113 for (let p of particles) {
114 p.update();
115 p.draw();
116 }
117
118 drawHUD();
119 }
120
121 function drawHUD() {
122 if (!showHUD) return;
123 textSize(14);
124 textLeading(18);
125 let lines = [
126 'Aurora Flow Field',
127 'Particles: ' + numParticles + ' | Mode: ' + mode + ' | Fade: ' + nf(fadeAlpha, 1, 2) + ' | Speed: ' + nf(speed, 1, 2),
128 '[r] reseed [c] mode [f] fade +/- [1/2] speed +/- [p] pause [s] save [h] HUD [space] clear'
129 ];
130 let pad = 10;
131 let wmax = 0;
132 for (let ln of lines) {
133 wmax = max(wmax, textWidth(ln));
134 }
135 let boxW = wmax + pad * 2;
136 let boxH = 18 * lines.length + pad * 2;
137 noStroke();
138 fill(0, 0, 0, 0.4);
139 rect(10, 10, boxW, boxH, 6);
140 fill(0, 0, 100, 1);
141 let y = 10 + pad + 12;
142 for (let ln of lines) {
143 text(ln, 10 + pad, y);
144 y += 18;
145 }
146 }
147
148 function keyPressed() {
149 if (key === 'r' || key === 'R') {
150 background(0);
151 init();
152 } else if (key === 'c' || key === 'C') {
153 mode = (mode + 1) % 4;
154 } else if (key === 'f' || key === 'F') {
155 if (keyIsDown(SHIFT)) fadeAlpha = max(0, fadeAlpha - 0.02);
156 else fadeAlpha = min(0.2, fadeAlpha + 0.02);
157 } else if (key === '1') {
158 speed = max(0.2, speed - 0.1);
159 } else if (key === '2') {
160 speed = min(4.0, speed + 0.1);
161 } else if (key === 'p' || key === 'P') {
162 paused = !paused;
163 } else if (key === 's' || key === 'S') {
164 saveCanvas('aurora_flow_' + seedVal, 'png');
165 } else if (key === 'h' || key === 'H') {
166 showHUD = !showHUD;
167 } else if (key === ' ') {
168 background(0);
169 }
170 }
171
172 function windowResized() {
173 resizeCanvas(windowWidth, windowHeight);
174 background(0);
175 init();
176 }
177