Source of: p5.js Perlin Flow Field, by DeepSeek V4.1 Flash 1017
87 lines, 6 of them comments ยท 1,550 tokens, written in 8 seconds for $0.0009
1 let particles = [];
2 const NUM = 1200;
3 const NOISE_SCALE = 0.0025;
4 let zOff = 0;
5
6 function setup() {
7 createCanvas(windowWidth, windowHeight);
8 colorMode(HSB, 360, 100, 100, 100);
9 background(0, 0, 3);
10
11 for (let i = 0; i < NUM; i++) {
12 particles.push(new Particle());
13 }
14 }
15
16 function draw() {
17 // Soft fade instead of clearing -> creates trailing streams
18 noStroke();
19 fill(0, 0, 3, 7);
20 rect(0, 0, width, height);
21
22 zOff += 0.0015;
23
24 for (const p of particles) {
25 p.update();
26 p.display();
27 }
28
29 // Reset the field occasionally to keep it fresh
30 if (frameCount % 1800 === 0) {
31 for (let i = 0; i < NUM; i++) particles[i] = new Particle();
32 background(0, 0, 3);
33 }
34 }
35
36 class Particle {
37 constructor() {
38 this.pos = createVector(random(width), random(height));
39 this.prev = this.pos.copy();
40 this.speed = random(0.8, 2.6);
41 this.hue = random(360);
42 }
43
44 update() {
45 this.prev.set(this.pos);
46
47 // Direction from Perlin noise (rotates smoothly over time)
48 const angle = noise(
49 this.pos.x * NOISE_SCALE,
50 this.pos.y * NOISE_SCALE,
51 zOff
52 ) * TAU * 2;
53
54 this.pos.x += cos(angle) * this.speed;
55 this.pos.y += sin(angle) * this.speed;
56
57 // Mouse repulsion
58 const dx = this.pos.x - mouseX;
59 const dy = this.pos.y - mouseY;
60 const distSq = dx * dx + dy * dy;
61 if (distSq < 12000) {
62 const f = (12000 - distSq) / 12000;
63 this.pos.x += dx * f * 0.05;
64 this.pos.y += dy * f * 0.05;
65 }
66
67 // Wrap around the edges
68 if (this.pos.x < 0) { this.pos.x = width; this.prev.x = width; }
69 if (this.pos.x > width) { this.pos.x = 0; this.prev.x = 0; }
70 if (this.pos.y < 0) { this.pos.y = height; this.prev.y = height; }
71 if (this.pos.y > height) { this.pos.y = 0; this.prev.y = 0; }
72
73 // Slowly shift hue
74 this.hue = (this.hue + 0.25) % 360;
75 }
76
77 display() {
78 stroke(this.hue, 85, 100, 35);
79 strokeWeight(1.2);
80 line(this.prev.x, this.prev.y, this.pos.x, this.pos.y);
81 }
82 }
83
84 function windowResized() {
85 resizeCanvas(windowWidth, windowHeight);
86 background(0, 0, 3);
87 }