177 lines, 2 of them comments ยท 5,864 tokens, written in 81 seconds for $0.059


  1  let particles = [];
  2  let numParticles;
  3  let noiseScale = 0.0015;
  4  let zOff = 0;
  5  let zInc = 0.002;
  6  let speed = 1.2;
  7  let hueShift = 0;
  8  let hueInc = 0.1;
  9  let fadeAlpha = 0.08; // 0..1
 10  let paused = false;
 11  let showHUD = true;
 12  let mode = 0; // color mode
 13  let seedVal;
 14  
 15  class Particle {
 16    constructor() {
 17      this.reset(true);
 18    }
 19    reset(randomPos = false) {
 20      if (randomPos) {
 21        this.pos = createVector(random(width), random(height));
 22      } else {
 23        let side = floor(random(4));
 24        if (side === 0) this.pos = createVector(random(width), -1);
 25        else if (side === 1) this.pos = createVector(width + 1, random(height));
 26        else if (side === 2) this.pos = createVector(random(width), height + 1);
 27        else this.pos = createVector(-1, random(height));
 28      }
 29      this.prev = this.pos.copy();
 30      this.hueOff = random(360);
 31    }
 32    update() {
 33      let nx = this.pos.x * noiseScale;
 34      let ny = this.pos.y * noiseScale;
 35      let angle = noise(nx, ny, zOff) * TWO_PI * 4.0;
 36      let v = p5.Vector.fromAngle(angle);
 37      v.mult(speed);
 38      this.pos.add(v);
 39  
 40      if (
 41        this.pos.x < -2 ||
 42        this.pos.x > width + 2 ||
 43        this.pos.y < -2 ||
 44        this.pos.y > height + 2
 45      ) {
 46        this.reset(false);
 47        this.prev = this.pos.copy();
 48      }
 49    }
 50    draw() {
 51      let h;
 52      if (mode === 0) {
 53        h = (hueShift + this.hueOff) % 360;
 54      } else if (mode === 1) {
 55        h = map(this.pos.x, 0, width, 0, 360);
 56      } else if (mode === 2) {
 57        let nx = this.pos.x * noiseScale;
 58        let ny = this.pos.y * noiseScale;
 59        let a = (noise(nx, ny, zOff) * 360 * 4.0) % 360;
 60        h = a;
 61      } else {
 62        let d = dist(this.pos.x, this.pos.y, mouseX, mouseY);
 63        h = map(d, 0, max(width, height), 200, 360) % 360;
 64      }
 65      stroke(h, 80, 100, 0.5);
 66      strokeWeight(1);
 67      line(this.prev.x, this.prev.y, this.pos.x, this.pos.y);
 68      this.prev.set(this.pos);
 69    }
 70  }
 71  
 72  function setup() {
 73    createCanvas(windowWidth, windowHeight);
 74    pixelDensity(1);
 75    colorMode(HSB, 360, 100, 100, 1);
 76    background(0);
 77    init();
 78  }
 79  
 80  function init() {
 81    seedVal = floor(random(1e9));
 82    randomSeed(seedVal);
 83    noiseSeed(seedVal);
 84    particles = [];
 85    numParticles = floor((width * height) / 2200);
 86    numParticles = constrain(numParticles, 400, 2500);
 87    for (let i = 0; i < numParticles; i++) {
 88      particles.push(new Particle());
 89    }
 90  }
 91  
 92  function draw() {
 93    if (paused) {
 94      drawHUD();
 95      return;
 96    }
 97  
 98    if (fadeAlpha > 0) {
 99      noStroke();
100      fill(0, 0, 0, fadeAlpha);
101      rect(0, 0, width, height);
102    }
103  
104    zOff += zInc;
105    hueShift = (hueShift + hueInc) % 360;
106  
107    if (mouseIsPressed) {
108      let mx = mouseX * noiseScale;
109      let my = mouseY * noiseScale;
110      zOff += 0.004 * sin(frameCount * 0.05 + noise(mx, my) * TWO_PI);
111    }
112  
113    for (let p of particles) {
114      p.update();
115      p.draw();
116    }
117  
118    drawHUD();
119  }
120  
121  function drawHUD() {
122    if (!showHUD) return;
123    textSize(14);
124    textLeading(18);
125    let lines = [
126      'Aurora Flow Field',
127      'Particles: ' + numParticles + '  |  Mode: ' + mode + '  |  Fade: ' + nf(fadeAlpha, 1, 2) + '  |  Speed: ' + nf(speed, 1, 2),
128      '[r] reseed  [c] mode  [f] fade +/-  [1/2] speed +/-  [p] pause  [s] save  [h] HUD  [space] clear'
129    ];
130    let pad = 10;
131    let wmax = 0;
132    for (let ln of lines) {
133      wmax = max(wmax, textWidth(ln));
134    }
135    let boxW = wmax + pad * 2;
136    let boxH = 18 * lines.length + pad * 2;
137    noStroke();
138    fill(0, 0, 0, 0.4);
139    rect(10, 10, boxW, boxH, 6);
140    fill(0, 0, 100, 1);
141    let y = 10 + pad + 12;
142    for (let ln of lines) {
143      text(ln, 10 + pad, y);
144      y += 18;
145    }
146  }
147  
148  function keyPressed() {
149    if (key === 'r' || key === 'R') {
150      background(0);
151      init();
152    } else if (key === 'c' || key === 'C') {
153      mode = (mode + 1) % 4;
154    } else if (key === 'f' || key === 'F') {
155      if (keyIsDown(SHIFT)) fadeAlpha = max(0, fadeAlpha - 0.02);
156      else fadeAlpha = min(0.2, fadeAlpha + 0.02);
157    } else if (key === '1') {
158      speed = max(0.2, speed - 0.1);
159    } else if (key === '2') {
160      speed = min(4.0, speed + 0.1);
161    } else if (key === 'p' || key === 'P') {
162      paused = !paused;
163    } else if (key === 's' || key === 'S') {
164      saveCanvas('aurora_flow_' + seedVal, 'png');
165    } else if (key === 'h' || key === 'H') {
166      showHUD = !showHUD;
167    } else if (key === ' ') {
168      background(0);
169    }
170  }
171  
172  function windowResized() {
173    resizeCanvas(windowWidth, windowHeight);
174    background(0);
175    init();
176  }
177