Code viewer for World: Scare the Fishes

See raw JS.

//base code from
// Daniel Shiffman
// http://codingtra.in
// http://patreon.com/codingtrain
// Code for: https://youtu.be/BjoM9oKOAKY


AB.drawRunControls = false;
AB.screenshotStep  = 2;   

//=== Start of the tweaker's box ==================================


var inc = 0.1;                  //changes how irregular the flowield and the particles behave
var scl = 10;                   //scale of the flowfield
let drawForceField = false;     //if set on true, will draw the forcefield underneath the particules
let radius = 150;               //distance at which the fishes get scared of the mouse
let nbParticles = 400;          //nb of particles (fishes)
let clickRadius = 200;          //distance at which the fishes get scared when mouse is pressed
let clickForceMultiplier = 10;  //Multiplies the force that pushes particles away from the mouse when mouse is pressed
let mouseForce = 300;           //Force at which particles are pushed away from the mouse


//=== End of the tweaker's box ====================================


function Particle() {
  this.pos = createVector(random(width), random(height));
  this.vel = createVector(0, 0);
  this.acc = createVector(0, 0);
  this.maxspeed = 4;
  this.h = random(255); //color of the particle
  this.prev = [];

  this.update = function() {
    this.vel.add(this.acc);
    if(this.vel.mag() > this.maxspeed) this.vel.mult(0.7);
    this.pos.add(this.vel);
    this.acc.mult(0);
    
    this.prev.unshift(this.pos.copy());
    if(this.prev.length >= 5)
    {
        this.prev.pop();
    }
    
  };

  this.follow = function(vectors) {
    var x = floor(this.pos.x / scl);
    var y = floor(this.pos.y / scl);
    var index = x + y * cols;
    var force = vectors[index];
    this.applyForce(force);
  };

  this.applyForce = function(force) {
    this.acc.add(force);
  };

  this.show = function() {
    stroke(this.h, 255, 255, 100);
    strokeWeight(3);
    for (let p of this.prev)
    {   
       point(p.x,p.y)
    }
    strokeWeight(6);
    point(this.pos.x, this.pos.y);
    
  };

 

  this.edges = function() {
    if (this.pos.x > width) {
      this.pos.x = 0;
      
    }
    if (this.pos.x < 0) {
      this.pos.x = width;
      
    }
    if (this.pos.y > height) {
      this.pos.y = 0;
      
    }
    if (this.pos.y < 0) {
      this.pos.y = height;
      
    }

  };

}

function World() 
{ 
	this.newRun = function()
	{
				threeworld.init (  "white"  ); 
	};
}



var cols, rows;
var zoff = 0;
var particles = [];
var flowfield;


function aftersetup()      
{
  colorMode(HSB, 255);
  cols = floor(width / scl);
  rows = floor(height / scl);

  flowfield = new Array(cols * rows);
  
//   if (AB.onMobile()) nbParticle = nbParticle/3; //This reduces lag on mobiles and prevents too much density

  for (var i = 0; i < nbParticles; i++) {
    particles[i] = new Particle();
  }
}



function draw()             
{
    background(30)
  var yoff = 0;
  for (var y = 0; y < rows; y++) {
    var xoff = 0;
    for (var x = 0; x < cols; x++) {
      var index = x + y * cols;
      var angle = noise(xoff, yoff, zoff) * TWO_PI * 4;
      var v = p5.Vector.fromAngle(angle);
      v.setMag(1);
      flowfield[index] = v;
      xoff += inc;
      stroke(0, 50);
      if(drawForceField)
      {
          push();
          translate(x * scl, y * scl);
          rotate(v.heading());
          strokeWeight(1);
          line(0, 0, scl, 0);
          pop();
      }
    }
    yoff += inc;

    zoff += 0.0003;
  }
  
  for(let y = 0; y<rows; y++)
  {
      for (let x = 0; x < cols; x++) 
      {
          
          let mouse = createVector(mouseX,mouseY);
          let point = createVector(x*scl, y*scl);
          let dist = mouse.dist(point); 
          if(mouseIsPressed)
          {
              if (dist < radius + clickRadius)
              {
                
                    let v = createVector(point.x - mouse.x, point.y - mouse.y);
                    v.setMag(mouseForce*clickForceMultiplier/dist);
                    flowfield[x + y*cols] = v;
        
              }
          }
          else
          {
              if (dist < radius)
              {
                
                    let v = createVector(point.x - mouse.x, point.y - mouse.y);
                    v.setMag(mouseForce/dist);
                    flowfield[x + y*cols] = v;
        
              }
          }
          
      }
  }

  for (var i = 0; i < particles.length; i++) {
    particles[i].follow(flowfield);
    particles[i].update();
    particles[i].edges();
    particles[i].show();
  }

}