100 lines, 5 of them comments ยท 1,319 tokens, written in 15 seconds for $0.0082


  1  let ribbons = [];
  2  const RIBBON_COUNT = 14;
  3  
  4  function setup() {
  5    createCanvas(windowWidth, windowHeight);
  6    colorMode(HSB, 360, 100, 100, 100);
  7    background(230, 40, 8);
  8    for (let i = 0; i < RIBBON_COUNT; i++) {
  9      ribbons.push(new Ribbon(i));
 10    }
 11  }
 12  
 13  function draw() {
 14    // Fade trails
 15    noStroke();
 16    fill(230, 40, 8, 8);
 17    rect(0, 0, width, height);
 18  
 19    for (let r of ribbons) {
 20      r.update();
 21      r.display();
 22    }
 23  }
 24  
 25  function windowResized() {
 26    resizeCanvas(windowWidth, windowHeight);
 27    background(230, 40, 8);
 28  }
 29  
 30  class Ribbon {
 31    constructor(idx) {
 32      this.idx = idx;
 33      this.reset();
 34    }
 35  
 36    reset() {
 37      this.points = [];
 38      this.xoff = random(1000);
 39      this.yoff = random(1000);
 40      this.zoff = random(1000);
 41      this.hue = random(140, 220);
 42      this.weight = random(1.5, 4.5);
 43      this.speed = random(0.002, 0.006);
 44      this.len = floor(random(40, 90));
 45      // seed a starting trail
 46      let x = random(width);
 47      let y = random(height);
 48      for (let i = 0; i < this.len; i++) {
 49        this.points.push(createVector(x, y));
 50      }
 51    }
 52  
 53    update() {
 54      let last = this.points[this.points.length - 1];
 55      let angle = noise(this.xoff, this.yoff, this.zoff) * TWO_PI * 2;
 56  
 57      // subtle mouse influence
 58      let mx = map(mouseX, 0, width, -0.4, 0.4);
 59      let my = map(mouseY, 0, height, -0.4, 0.4);
 60      angle += mx + my;
 61  
 62      let step = map(noise(this.zoff + 50), 0, 1, 1.5, 4);
 63      let nx = last.x + cos(angle) * step;
 64      let ny = last.y + sin(angle) * step;
 65  
 66      // wrap softly
 67      if (nx < -50) nx = width + 50;
 68      if (nx > width + 50) nx = -50;
 69      if (ny < -50) ny = height + 50;
 70      if (ny > height + 50) ny = -50;
 71  
 72      this.points.push(createVector(nx, ny));
 73      if (this.points.length > this.len) this.points.shift();
 74  
 75      this.xoff += this.speed;
 76      this.yoff += this.speed * 0.7;
 77      this.zoff += this.speed * 0.3;
 78      this.hue = (this.hue + 0.05) % 360;
 79    }
 80  
 81    display() {
 82      noFill();
 83      strokeWeight(this.weight);
 84      beginShape();
 85      for (let i = 0; i < this.points.length; i++) {
 86        let p = this.points[i];
 87        let t = i / this.points.length;
 88        let alpha = map(t, 0, 1, 0, 55);
 89        stroke(this.hue, 70, 90, alpha);
 90        curveVertex(p.x, p.y);
 91      }
 92      endShape();
 93  
 94      // soft glow dots at the head
 95      let head = this.points[this.points.length - 1];
 96      noStroke();
 97      fill(this.hue, 60, 100, 30);
 98      circle(head.x, head.y, this.weight * 3);
 99    }
100  }