Source of: Flow Field Particle System, by Qwen3.7 Max
93 lines, 3 of them comments ยท 1,111 tokens, written in 15 seconds for $0.0049
1 const PARTICLE_COUNT = 1500;
2 const NOISE_SCALE = 0.005;
3 const SPEED = 2.5;
4 const FADE = 15;
5
6 let particles = [];
7 let zoff = 0;
8
9 function setup() {
10 createCanvas(windowWidth, windowHeight);
11 background(0);
12 for (let i = 0; i < PARTICLE_COUNT; i++) {
13 particles.push(new Particle());
14 }
15 }
16
17 function draw() {
18 // Fade previous frame for trails
19 noStroke();
20 fill(0, FADE);
21 rect(0, 0, width, height);
22
23 for (let p of particles) {
24 p.follow();
25 p.update();
26 p.edges();
27 p.show();
28 }
29
30 zoff += 0.001;
31 }
32
33 class Particle {
34 constructor() {
35 this.pos = createVector(random(width), random(height));
36 this.vel = createVector(0, 0);
37 this.acc = createVector(0, 0);
38 this.maxSpeed = SPEED;
39 this.hue = random(360);
40 }
41
42 follow() {
43 // Perlin noise flow field, distorted by mouse position
44 let dx = mouseX - this.pos.x;
45 let dy = mouseY - this.pos.y;
46 let distMouse = sqrt(dx * dx + dy * dy);
47 let mouseInfluence = constrain(1 - distMouse / 200, 0, 1);
48
49 let angle = noise(this.pos.x * NOISE_SCALE,
50 this.pos.y * NOISE_SCALE,
51 zoff) * TWO_PI * 4;
52 angle += mouseInfluence * atan2(dy, dx) * 0.5;
53
54 let force = p5.Vector.fromAngle(angle);
55 force.setMag(0.2);
56 this.acc.add(force);
57 }
58
59 update() {
60 this.vel.add(this.acc);
61 this.vel.limit(this.maxSpeed);
62 this.pos.add(this.vel);
63 this.acc.mult(0);
64 this.hue = (this.hue + 0.3) % 360;
65 }
66
67 edges() {
68 if (this.pos.x > width) this.pos.x = 0;
69 if (this.pos.x < 0) this.pos.x = width;
70 if (this.pos.y > height) this.pos.y = 0;
71 if (this.pos.y < 0) this.pos.y = height;
72 }
73
74 show() {
75 colorMode(HSB, 360, 100, 100, 100);
76 stroke(this.hue, 80, 95, 60);
77 strokeWeight(1.2);
78 point(this.pos.x, this.pos.y);
79 }
80 }
81
82 function windowResized() {
83 resizeCanvas(windowWidth, windowHeight);
84 background(0);
85 }
86
87 function mousePressed() {
88 // Reset canvas on click
89 background(0);
90 for (let p of particles) {
91 p.pos = createVector(random(width), random(height));
92 }
93 }