Source of: Bioluminescent Flow Fields, by Gemini 3.7 Flash
88 lines, no comments ยท 2,396 tokens, written in 17 seconds for $0.0091
1 let particles = [];
2 const numParticles = 800;
3 let noiseScale = 0.004;
4 let noiseZ = 0;
5
6 function setup() {
7 createCanvas(windowWidth, windowHeight);
8 colorMode(HSB, 360, 100, 100, 100);
9 background(230, 40, 6);
10 for (let i = 0; i < numParticles; i++) {
11 particles.push(new Particle());
12 }
13 }
14
15 function draw() {
16 background(230, 40, 6, 10);
17
18 noiseZ += 0.003;
19 let mousePos = createVector(mouseX, mouseY);
20
21 for (let p of particles) {
22 p.update(mousePos);
23 p.display();
24 }
25 }
26
27 class Particle {
28 constructor() {
29 this.reset();
30 }
31
32 reset() {
33 this.pos = createVector(random(width), random(height));
34 this.prevPos = this.pos.copy();
35 this.vel = createVector(0, 0);
36 this.acc = createVector(0, 0);
37 this.maxSpeed = random(1.8, 3.8);
38 this.hueOffset = random(0, 80);
39 this.weight = random(1, 2.5);
40 }
41
42 update(mousePos) {
43 this.prevPos = this.pos.copy();
44
45 let n = noise(this.pos.x * noiseScale, this.pos.y * noiseScale, noiseZ);
46 let angle = n * TWO_PI * 3;
47 let flow = p5.Vector.fromAngle(angle).mult(0.6);
48
49 this.acc.add(flow);
50
51 let d = dist(this.pos.x, this.pos.y, mousePos.x, mousePos.y);
52 if (mouseIsPressed && d < 200) {
53 let force = p5.Vector.sub(this.pos, mousePos);
54 force.setMag(map(d, 0, 200, 4, 0));
55 this.acc.add(force);
56 } else if (d < 120) {
57 let force = p5.Vector.sub(this.pos, mousePos);
58 force.setMag(map(d, 0, 120, 1.8, 0));
59 this.acc.add(force);
60 }
61
62 this.vel.add(this.acc);
63 this.vel.limit(this.maxSpeed);
64 this.pos.add(this.vel);
65 this.acc.mult(0);
66
67 if (this.pos.x < 0 || this.pos.x > width || this.pos.y < 0 || this.pos.y > height) {
68 this.pos.set(random(width), random(height));
69 this.prevPos = this.pos.copy();
70 }
71 }
72
73 display() {
74 let speed = this.vel.mag();
75 let h = (frameCount * 0.3 + this.pos.x * 0.08 + this.pos.y * 0.08 + this.hueOffset) % 360;
76 let b = map(speed, 0, this.maxSpeed, 70, 100);
77 let alpha = map(speed, 0, this.maxSpeed, 35, 90);
78
79 stroke(h, 85, b, alpha);
80 strokeWeight(this.weight);
81 line(this.prevPos.x, this.prevPos.y, this.pos.x, this.pos.y);
82 }
83 }
84
85 function windowResized() {
86 resizeCanvas(windowWidth, windowHeight);
87 background(230, 40, 6);
88 }