95 lines, no comments ยท 1,287 tokens, written in 14 seconds for $0.034


 1  let particles = [];
 2  let flowfield;
 3  let cols, rows;
 4  const scl = 20;
 5  let zoff = 0;
 6  let hueOffset = 0;
 7  
 8  function setup() {
 9    createCanvas(windowWidth, windowHeight);
10    colorMode(HSB, 360, 100, 100, 100);
11    cols = floor(width / scl);
12    rows = floor(height / scl);
13    flowfield = new Array(cols * rows);
14    for (let i = 0; i < 300; i++) {
15      particles.push(new Particle());
16    }
17    background(230, 30, 10);
18  }
19  
20  function draw() {
21    noStroke();
22    fill(230, 30, 10, 5);
23    rect(0, 0, width, height);
24  
25    let yoff = 0;
26    for (let y = 0; y < rows; y++) {
27      let xoff = 0;
28      for (let x = 0; x < cols; x++) {
29        const index = x + y * cols;
30        const angle = noise(xoff, yoff, zoff) * TWO_PI * 2;
31        const v = p5.Vector.fromAngle(angle);
32        v.setMag(0.3);
33        flowfield[index] = v;
34        xoff += 0.1;
35      }
36      yoff += 0.1;
37    }
38    zoff += 0.003;
39    hueOffset += 0.2;
40  
41    for (const p of particles) {
42      p.follow(flowfield);
43      p.update();
44      p.edges();
45      p.show();
46    }
47  }
48  
49  function windowResized() {
50    resizeCanvas(windowWidth, windowHeight);
51    cols = floor(width / scl);
52    rows = floor(height / scl);
53    flowfield = new Array(cols * rows);
54    background(230, 30, 10);
55  }
56  
57  class Particle {
58    constructor() {
59      this.pos = createVector(random(width), random(height));
60      this.vel = createVector(0, 0);
61      this.acc = createVector(0, 0);
62      this.maxSpeed = 2.5;
63      this.prev = this.pos.copy();
64      this.h = random(360);
65    }
66    follow(vectors) {
67      const x = floor(this.pos.x / scl);
68      const y = floor(this.pos.y / scl);
69      const index = x + y * cols;
70      const force = vectors[index];
71      if (force) this.acc.add(force);
72    }
73    update() {
74      this.vel.add(this.acc);
75      this.vel.limit(this.maxSpeed);
76      this.pos.add(this.vel);
77      this.acc.mult(0);
78    }
79    show() {
80      stroke((this.h + hueOffset) % 360, 80, 100, 40);
81      strokeWeight(1.2);
82      line(this.pos.x, this.pos.y, this.prev.x, this.prev.y);
83      this.updatePrev();
84    }
85    updatePrev() {
86      this.prev.x = this.pos.x;
87      this.prev.y = this.pos.y;
88    }
89    edges() {
90      if (this.pos.x > width) { this.pos.x = 0; this.updatePrev(); }
91      if (this.pos.x < 0) { this.pos.x = width; this.updatePrev(); }
92      if (this.pos.y > height) { this.pos.y = 0; this.updatePrev(); }
93      if (this.pos.y < 0) { this.pos.y = height; this.updatePrev(); }
94    }
95  }