Source of: Aurora Flow Garden, by GPT-5.5
156 lines, no comments ยท 1,632 tokens, written in 16 seconds for $0.049
1 let particles = [];
2 let palette;
3 let zoff = 0;
4 let paused = false;
5 let seed;
6
7 function setup() {
8 createCanvas(windowWidth, windowHeight);
9 pixelDensity(1);
10 colorMode(HSB, 360, 100, 100, 100);
11 seed = floor(random(100000));
12 resetSketch();
13 }
14
15 function resetSketch() {
16 randomSeed(seed);
17 noiseSeed(seed);
18 background(230, 45, 5);
19
20 palette = [
21 color(178, 85, 95, 18),
22 color(205, 90, 100, 16),
23 color(265, 75, 98, 14),
24 color(315, 70, 100, 12),
25 color(55, 80, 100, 10)
26 ];
27
28 particles = [];
29 let count = floor((width * height) / 5200);
30 count = constrain(count, 120, 420);
31
32 for (let i = 0; i < count; i++) {
33 particles.push(new FlowParticle(random(width), random(height)));
34 }
35 }
36
37 function draw() {
38 if (paused) return;
39
40 noStroke();
41 fill(232, 45, 5, 5);
42 rect(0, 0, width, height);
43
44 drawGlowBands();
45
46 blendMode(ADD);
47 for (let p of particles) {
48 p.update();
49 p.display();
50 }
51 blendMode(BLEND);
52
53 zoff += 0.003;
54 }
55
56 function drawGlowBands() {
57 blendMode(ADD);
58 noFill();
59 for (let j = 0; j < 4; j++) {
60 let hue = 175 + j * 28 + sin(frameCount * 0.01 + j) * 15;
61 stroke(hue, 70, 95, 3.5);
62 strokeWeight(18 + j * 7);
63 beginShape();
64 for (let x = -40; x <= width + 40; x += 32) {
65 let n = noise(x * 0.0025, j * 20, zoff * 0.8);
66 let y = height * (0.32 + j * 0.115) + map(n, 0, 1, -90, 90);
67 curveVertex(x, y);
68 }
69 endShape();
70 }
71 blendMode(BLEND);
72 }
73
74 class FlowParticle {
75 constructor(x, y) {
76 this.pos = createVector(x, y);
77 this.prev = this.pos.copy();
78 this.vel = p5.Vector.random2D().mult(random(0.2, 1.4));
79 this.acc = createVector(0, 0);
80 this.maxSpeed = random(1.0, 3.2);
81 this.weight = random(0.4, 2.1);
82 this.life = random(120, 520);
83 this.age = random(this.life);
84 this.col = random(palette);
85 this.noiseScale = random(0.0015, 0.0045);
86 }
87
88 update() {
89 this.prev.set(this.pos);
90
91 let n = noise(this.pos.x * this.noiseScale, this.pos.y * this.noiseScale, zoff);
92 let angle = n * TWO_PI * 4.0 + sin(zoff * 3 + this.pos.y * 0.004) * 0.8;
93 let force = p5.Vector.fromAngle(angle).mult(0.08);
94
95 let centerPull = createVector(width / 2, height / 2).sub(this.pos);
96 centerPull.setMag(0.002);
97
98 this.acc.add(force);
99 this.acc.add(centerPull);
100 this.vel.add(this.acc);
101 this.vel.limit(this.maxSpeed);
102 this.pos.add(this.vel);
103 this.acc.mult(0);
104
105 this.age++;
106 if (this.pos.x < -20 || this.pos.x > width + 20 || this.pos.y < -20 || this.pos.y > height + 20 || this.age > this.life) {
107 this.rebirth();
108 }
109 }
110
111 display() {
112 let alphaPulse = map(sin(this.age * 0.06), -1, 1, 5, 25);
113 let c = color(hue(this.col), saturation(this.col), brightness(this.col), alphaPulse);
114 stroke(c);
115 strokeWeight(this.weight);
116 line(this.prev.x, this.prev.y, this.pos.x, this.pos.y);
117
118 if (random() < 0.025) {
119 noStroke();
120 fill(hue(this.col), 70, 100, 18);
121 circle(this.pos.x, this.pos.y, random(1, 5));
122 }
123 }
124
125 rebirth() {
126 if (random() < 0.55) {
127 this.pos.set(random(width), random(height));
128 } else {
129 let side = floor(random(4));
130 if (side === 0) this.pos.set(random(width), -5);
131 if (side === 1) this.pos.set(width + 5, random(height));
132 if (side === 2) this.pos.set(random(width), height + 5);
133 if (side === 3) this.pos.set(-5, random(height));
134 }
135 this.prev.set(this.pos);
136 this.vel = p5.Vector.random2D().mult(random(0.2, 1.2));
137 this.life = random(120, 520);
138 this.age = 0;
139 this.col = random(palette);
140 }
141 }
142
143 function mousePressed() {
144 seed = floor(random(100000));
145 resetSketch();
146 }
147
148 function keyPressed() {
149 if (key === ' ') paused = !paused;
150 if (key === 's' || key === 'S') saveCanvas('aurora-flow-garden', 'png');
151 }
152
153 function windowResized() {
154 resizeCanvas(windowWidth, windowHeight);
155 resetSketch();
156 }