89 lines, no comments ยท 1,361 tokens, written in 18 seconds for $0.029


 1  let particles = [];
 2  const NUM = 2500;
 3  let zoff = 0;
 4  let seedVal;
 5  
 6  function setup() {
 7    createCanvas(windowWidth, windowHeight);
 8    colorMode(HSB, 360, 100, 100, 100);
 9    reseed();
10  }
11  
12  function reseed() {
13    seedVal = floor(random(100000));
14    noiseSeed(seedVal);
15    background(230, 40, 8);
16    particles = [];
17    for (let i = 0; i < NUM; i++) {
18      particles.push(new Particle());
19    }
20  }
21  
22  function draw() {
23    noStroke();
24    fill(230, 40, 8, 4);
25    rect(0, 0, width, height);
26    zoff += 0.0015;
27    for (const p of particles) {
28      p.update();
29      p.show();
30    }
31  }
32  
33  class Particle {
34    constructor() {
35      this.reset();
36    }
37    reset() {
38      this.pos = createVector(random(width), random(height));
39      this.prev = this.pos.copy();
40      this.vel = createVector(0, 0);
41      this.life = random(100, 400);
42      this.hueOff = random(-25, 25);
43    }
44    update() {
45      const scl = 0.0025;
46      const n = noise(this.pos.x * scl, this.pos.y * scl, zoff);
47      const angle = n * TWO_PI * 4;
48      const force = p5.Vector.fromAngle(angle).mult(0.35);
49      this.vel.add(force);
50      if (mouseIsPressed === false) {
51        const d = dist(mouseX, mouseY, this.pos.x, this.pos.y);
52        if (d < 120 && d > 0.1) {
53          const away = createVector(this.pos.x - mouseX, this.pos.y - mouseY);
54          away.setMag(map(d, 0, 120, 1.5, 0));
55          this.vel.add(away);
56        }
57      }
58      this.vel.limit(2.5);
59      this.prev.set(this.pos);
60      this.pos.add(this.vel);
61      this.life--;
62      if (this.life < 0 || this.pos.x < 0 || this.pos.x > width || this.pos.y < 0 || this.pos.y > height) {
63        this.reset();
64      }
65    }
66    show() {
67      const n = noise(this.pos.x * 0.001, this.pos.y * 0.001, zoff * 2);
68      const h = (map(n, 0, 1, 160, 340) + this.hueOff + frameCount * 0.1) % 360;
69      stroke(h, 70, 95, 25);
70      strokeWeight(1.2);
71      line(this.prev.x, this.prev.y, this.pos.x, this.pos.y);
72    }
73  }
74  
75  function mousePressed() {
76    reseed();
77  }
78  
79  function keyPressed() {
80    if (key === 's' || key === 'S') {
81      saveCanvas('flowfield_' + seedVal, 'png');
82    }
83  }
84  
85  function windowResized() {
86    resizeCanvas(windowWidth, windowHeight);
87    background(230, 40, 8);
88  }
89