Removing mouse controls from Javascript code

Viewed 74

I have a large piece of code that draws feather-looking designs controlled by the mouse. This is using mouse pressed and mouseX, mouseY.

I would like the code to run and draw the feathers without the mouse being involved (ie. opening the canvas and having feathers automatically draw on the screen).

The full code is below:

var points = [];
var painting = false;
var strokeNumber = 0;

var scl = 6;
var cols, rows;
var inc = 0.1;
var zOff = 0;
var particles = [];
var flowField = [];
var saturation = [];

function setup() {
  createCanvas(windowWidth, windowHeight);
  // createCanvas(400, 400);
  
  pixelDensity(5);
  background(0);
  
  cols = floor(width / scl);
  rows = floor(height / scl);
  
  flowField = Array(cols * rows);
  saturation = Array(width * height).fill(0);
  greateForceField();
  
}

function mousePressed() {
  painting = true;
  strokeNumber++;
}

function mouseReleased() {
  painting = false;
}

function updateForceField(){
  var v = createVector(mouseX, mouseY);
  var vPrev = createVector(pmouseX, pmouseY);
  v.sub(vPrev);
  v.setMag(1);
  var i = floor(mouseX / scl);
  var j = floor(mouseY / scl);
  var index =  i * rows + j;
  flowField[index] = v;
}

function showForceField(){
  for(var i = 0; i < cols; i++){
    for(var j = 0; j < rows; j++){
      var index = i * rows + j;
      var v = flowField[index];
      stroke(0,50);
      strokeWeight(1);
      push();      
      translate(i * scl, j * scl);
      rotate(v.heading());
      line(0,0,scl,0);
      pop();
    }    
  }
}

function greateForceField(){
  var xOff = 0;
  for(var i = 0; i < cols; i++){
    var yOff = 0;
    for(var j = 0; j < rows; j++){
      yOff += inc; 
      var angle = noise(xOff, yOff, zOff) * TWO_PI;
      var v = p5.Vector.fromAngle(angle);
      v.setMag(.1);
      var index = i * rows + j;
      flowField[index] = v;
    }
    xOff += inc;
  }
  // zOff += inc * 0.1;
}

function draw() {
  // background(255);
  // showForceField();
  
  if(painting){
    updateForceField();

    var idx = mouseY * width + mouseX;
    if(saturation[idx] < 10){
      var r = 1+sqrt(sq(mouseX-pmouseX)+sq(mouseY-pmouseY));
      for(var a = 0; a < 100; a++){
        var particle = new Particle(mouseX+random()*r*cos(random(TWO_PI)), mouseY+random()*r*sin(random(TWO_PI)));
        particles.push(particle);
      }
      saturation[idx] ++;
    }
  }
  
  particles.filter(particle => particle.spread > 0).map(particle => {
    particle.update();
    particle.show();
    // particle.edges();
    particle.follow();
  })
  
  particles.map((particle, idx) => {
    if(particle.spread <= 0){
      particles.splice(idx,1);
    }
  });
  
}

function Particle(x,y){  
  this.pos = createVector(x,y);
  // this.color = color(245, 225, 50);
  // this.color = color(145, 225, 192);
  this.color = color(255);
  this.spread = 127;
  this.spreadInc = this.spread/100;
  
  this.prevPos = this.pos.copy();
  this.vel = p5.Vector.random2D();
  this.acc = createVector(0,0);
  this.maxSpeed = 2;
  
  this.update = function(){
    this.spread -= this.spreadInc;
    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.follow = function(){
    var i = floor(this.pos.x / scl);
    var j = floor(this.pos.y / scl);
    var index =  i * rows + j;
    var force = flowField[index];
    this.applyForce(force);    
  }
  
  this.show = function(){
    stroke(red(this.color),green(this.color),blue(this.color),this.spread);
    strokeWeight(.3*this.spread/127);
    // point(this.pos.x, this.pos.y);
    line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
    this.updatePrev();
  }
  
  this.updatePrev = function(){
    this.prevPos = this.pos.copy();
  }
  
  this.edges = function(){
    if(this.pos.x > width) {
      this.pos.x = 0;
      this.updatePrev();
    }
    if(this.pos.x < 0){
      this.pos.x = width;
      this.updatePrev();
    }
    if(this.pos.y > height){
      this.pos.y = 0;
      this.updatePrev();
    }
    if(this.pos.y < 0) {
      this.pos.y = height;
      this.updatePrev();
    }

  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>

1 Answers

Use 4 variables current_x, current_y, prev_x and prev_y instead of mosueX, mouseY, pmouseX and pmouseY.

var current_x=0, current_y=0, prev_x=0, prev_y=0;

function updateForceField(){
    var v = createVector(current_x, current_y);
    var vPrev = createVector(prev_x, prev_y);
    v.sub(vPrev);
    v.setMag(1);
    var i = floor(current_x / scl);
    var j = floor(current_y / scl);
    var index =  i * rows + j;
    flowField[index] = v;
}

Instead of the state painting use a time interval. The time between 2 frames can be get from the built-in variable deltaTime (in milliseconds). Set the x and y positions by random values. e.g.:

var interval = 200; // 200 milliseconds
var sum_time = 0;

function draw() {

    sum_time += deltaTime;
    if(sum_time > interval){
        sum_time = 0;

        current_x = Math.floor(random(width));
        current_y = Math.floor(random(height));
        updateForceField();
        prev_x = current_x;
        prev_y = current_y; 

        var idx = current_y * width + current_x;
        if(saturation[idx] < 10){
            var r = 1+sqrt(sq(current_x-prev_x)+sq(current_y-prev_y));
            for(var a = 0; a < 100; a++){
                var particle = new Particle(current_x+random()*r*cos(random(TWO_PI)), current_y+random()*r*sin(random(TWO_PI)));
                particles.push(particle);
            }
            saturation[idx] ++;
        }
    }

    // [...]
}

See the example:

var points = [];
var painting = false;
var strokeNumber = 0;

var scl = 6;
var cols, rows;
var inc = 0.1;
var zOff = 0;
var particles = [];
var flowField = [];
var saturation = [];

function setup() {
  //createCanvas(windowWidth, windowHeight);
  createCanvas(500, 200);

  pixelDensity(5);
  background(0);

  cols = floor(width / scl);
  rows = floor(height / scl);

  flowField = Array(cols * rows);
  saturation = Array(width * height).fill(0);
  greateForceField();

}

function mousePressed() {
  painting = true;
  strokeNumber++;
}

function mouseReleased() {
  painting = false;
}

var current_x=0, current_y=0, prev_x=0, prev_y=0;

function updateForceField(){
    var v = createVector(current_x, current_y);
    var vPrev = createVector(prev_x, prev_y);
    v.sub(vPrev);
    v.setMag(1);
    var i = floor(current_x / scl);
    var j = floor(current_y / scl);
    var index =  i * rows + j;
    flowField[index] = v;
}

function showForceField(){
  for(var i = 0; i < cols; i++){
    for(var j = 0; j < rows; j++){
      var index = i * rows + j;
      var v = flowField[index];
      stroke(0,50);
      strokeWeight(1);
      push();      
      translate(i * scl, j * scl);
      rotate(v.heading());
      line(0,0,scl,0);
      pop();
    }    
  }
}

function greateForceField(){
  var xOff = 0;
  for(var i = 0; i < cols; i++){
    var yOff = 0;
    for(var j = 0; j < rows; j++){
      yOff += inc; 
      var angle = noise(xOff, yOff, zOff) * TWO_PI;
      var v = p5.Vector.fromAngle(angle);
      v.setMag(.1);
      var index = i * rows + j;
      flowField[index] = v;
    }
    xOff += inc;
  }
  // zOff += inc * 0.1;
}

var interval = 200; // 200 milliseconds
var sum_time = 0;

function draw() {
    // background(255);
    // showForceField();

    sum_time += deltaTime;
    if(sum_time > interval){
        sum_time = 0;

        current_x = Math.floor(random(width));
        current_y = Math.floor(random(height));
        updateForceField();
        prev_x = current_x;
        prev_y = current_y; 

        var idx = current_y * width + current_x;
        if(saturation[idx] < 10){
            var r = 1+sqrt(sq(current_x-prev_x)+sq(current_y-prev_y));
            for(var a = 0; a < 100; a++){
                var particle = new Particle(current_x+random()*r*cos(random(TWO_PI)), current_y+random()*r*sin(random(TWO_PI)));
                particles.push(particle);
            }
            saturation[idx] ++;
        }
    }

    particles.filter(particle => particle.spread > 0).map(particle => {
        particle.update();
        particle.show();
        // particle.edges();
        particle.follow();
    })

    particles.map((particle, idx) => {
        if(particle.spread <= 0){
            particles.splice(idx,1);
        }
    });
}

function Particle(x,y){  
  this.pos = createVector(x,y);
  // this.color = color(245, 225, 50);
  // this.color = color(145, 225, 192);
  this.color = color(255);
  this.spread = 127;
  this.spreadInc = this.spread/100;

  this.prevPos = this.pos.copy();
  this.vel = p5.Vector.random2D();
  this.acc = createVector(0,0);
  this.maxSpeed = 2;

  this.update = function(){
    this.spread -= this.spreadInc;
    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.follow = function(){
    var i = floor(this.pos.x / scl);
    var j = floor(this.pos.y / scl);
    var index =  i * rows + j;
    var force = flowField[index];
    this.applyForce(force);    
  }

  this.show = function(){
    stroke(red(this.color),green(this.color),blue(this.color),this.spread);
    strokeWeight(.3*this.spread/127);
    // point(this.pos.x, this.pos.y);
    line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
    this.updatePrev();
  }

  this.updatePrev = function(){
    this.prevPos = this.pos.copy();
  }

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

  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>

Related