submission by jtoy for superheroes (View the other submissions)
function Particle(){
  this.pos = createVector(random(width),random(height))
  this.prev_pos = this.pos.copy()
  this.vel = createVector(0,0)
  this.acc = createVector(0,0)
  this.sw = random(5,20)
  this.col = color(random(255),random(255),random(255))
  this.maxspeed = random(0,10)
  this.update = function(){
    this.vel.add(this.acc)
    this.vel.limit(this.maxspeed)
    this.pos.add(this.vel)
    this.acc.mult(0)
  }
  this.applyForce = function(force){
    this.acc.add(force)
  }
  this.set_prev = function(){
    this.prev_pos.x = this.pos.x
    this.prev_pos.y = this.pos.y
  }
  this.show = function(){
    stroke(this.col,5)
    strokeWeight(this.sw)
    //point(this.pos.x,this.pos.y)
    line(this.pos.x,this.pos.y,this.prev_pos.x,this.prev_pos.y)
    this.set_prev()
 
  }
  this.edges = function(){
        if(width - this.pos.x < 5 && this.pos.x === this.prev_pos.x){
      this.pos.x = 0
    }

    if(this.pos.x > width){
      
     this.pos.x=1
     //this.pos.x = this.pos.x%width
     this.set_prev()
    }
    if(this.pos.x < 0){
      
    this.pos.x=width-1
    this.set_prev()
    }
    if(this.pos.y > height){
      
    this.pos.y=1
         //this.pos.y = this.pos.y%height

    this.set_prev()
  
    }
    
    if(this.pos.y < 0){
      
      this.pos.y=height-1
      this.set_prev()
    }

  }
  this.follow_flowfield = 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]
    //console.log(force)
    this.applyForce(force)
  }
}


function setup() {
  var myCanvas = createCanvas(800,800); //you must keep this line unmodified
  yoff = 0.0; 
  angle = radians(-10)
  follow = true
  particles  = []
  scl = 20
  tt=0
  inc=0
  warp = false
  warp_time = millis()
  c1 = noise(tt+1)*255
  c2 = noise(tt+2)*255
  c3 = noise(tt+3)*255
  cols = floor(width/scl)
  rows = floor(height/scl)
  flowfield = new Array(cols*rows)
  for(i=0;i<200;i++){
    particles[i]= new Particle()
  }
}
function w(v){
  return v * width;
}
function h(v){
  return v * height;
}
function draw() {
 
  if(millis() -warp_time > 5000){

    if(warp === false){
      warp = true
    }else{
      warp = false
    }
    warp_time=millis()
    console.log('warp')
  }
  if(!warp){
    c =color(noise(tt+1)*255,noise(tt+2)*255,noise(tt+3)*255)
    background(c,5)
  }
  for(y=0;y< rows;y++){
    xoff = 0
    for(x=0;x<cols;x++){
      index = x + y * cols
      v = p5.Vector.fromAngle(angle-radians(180))
      flowfield[index] = v
      xoff += inc
    }
  }
  for(i=0;i<particles.length;i++){
    particles[i].follow_flowfield(flowfield)
    particles[i].update()
    particles[i].edges()
    particles[i].show()
  }
  
  
  noStroke()
  push()
  fill(255)
  translate(width/2,height/2)
  rotate(angle)
  fill(255,0,0)
  fill(0,0,255)
  rect(0,0,w(0.4),w(0.12),40)
  fill(255,100,0)
  rect(-w(0.25),0,w(0.5),w(0.15),40)
  fill(235,199,161)
  ellipse(w(0.25),-h(0.1),w(0.25),w(0.25))
  fill(255,255,0)
  rect(w(0.1),-h(0.001),w(0.35),w(0.12),40)
  fill(0)
  ellipse(w(0.4),h(0.053),w(0.15),w(0.15))
  fill(0,0,255)
  rect(-w(0.45),h(0.006),w(0.3),w(0.12),40)

  //stroke(0)
  
   //fill(255);
  beginShape(); 
   var xoff = yoff; // Option #2: 1D Noise

  for (var x = -w(0.35); x <= w(0.13); x += 10) {
     var y = map(noise(xoff), 0, 1, 0,40);
    // Set the vertex
    vertex(x, -y); 
    xoff += 0.05;
  }
  yoff += 0.01;

  vertex(w(0.15),0)  
  vertex(-x,-y-30)
  fill(255,0,0)
  endShape(CLOSE);
  pop()
  if(follow ===true) angle = atan2(mouseY-height/2, mouseX-width/2);
 
 tt += 0.01
}
function mouseReleased() {
  if(follow === true){
    follow = false;
  }else{
   follow = true 
  }
  console.log('wtf')
}