Set attractor/repeller corresponding to mouse pressed LEFT/RIGHT

Hi am trying to modify the “Attraction and Repulsion Forces” NOC tutorial code and set either an attractor or repeller on mouse LEFT(attractor) or RIGHT(repeller) pressed into the canvas. I got something working but when I click the mouse it resets all previous attractors/repellers. Any idea how I have to structure my code so I can have individual attractors and repellers?

sketch.js

var attractors = [];
var particles = [];

function setup() {
  createCanvas(400, 400);
  for (var i = 0; i < 100; i++) {
    particles.push(new Particle(random(width), random(height)));
  }
}

function mousePressed() {
  attractors.push(createVector(mouseX, mouseY));
}

function draw() {
  background(51);

  strokeWeight(4);
  for (var i = 0; i < attractors.length; i++) {
    
    if (mouseButton === LEFT) {
      stroke(0, 255, 0);
    } else { if (mouseButton === RIGHT) {
      stroke(255, 0, 0);
    }} 
    point(attractors[i].x, attractors[i].y);
  }

  for (var i = 0; i < particles.length; i++) {
    for (var j = 0; j < attractors.length; j++) {
      particles[i].attracted(attractors[j], j);
    }

    particles[i].update();
    particles[i].show();
  }
}

particle.js

function Particle(x, y) {
  this.pos = createVector(x, y);
  this.vel = createVector();

  this.acc = createVector();
  this.maxspeed = 6;

  this.update = function () {
    this.vel.add(this.acc);
    this.vel.limit(this.maxspeed);
    this.pos.add(this.vel);
    this.acc.mult(0);
  };

  this.show = function () {
    stroke(255);
    strokeWeight(4);
    point(this.pos.x, this.pos.y);
  };

  this.attracted = function (target, j) {
    //var dir = target -this.pos
    var force = p5.Vector.sub(target, this.pos);
    var dsquared = force.magSq();
    dsquared = constrain(dsquared, 5, 50);
    var G = 10;
    var strength = G / dsquared;
    force.setMag(strength);

    if (j == (mouseButton === LEFT)) {
      force.mult(-1);
    } else {
      if (j == (mouseButton === RIGHT)) {
        force.mult(1);
      }
    }
    this.acc.add(force);
  };
}

better

    if (mouseButton === LEFT) {
      stroke(0, 255, 0);
    } else if (mouseButton === RIGHT) {
      stroke(255, 0, 0);
    }

Remark: else if is a keyword like if

This occurs in the class also.

What you have to do:

As you can see from the colors of the points: they all
show always the same color.

This is because you only check the last / current mouse click (mouseButton === LEFT). This is wrong.

Instead you need to store this info (mouseButton === LEFT) for each new attractor separately / individually (I am an attractor / I am a Repulsor).

Either make a proper Attractor class or make a parallel array to
var attractors = []; where you store this.

Example

var attractors = []; // Vector
var attractorsKind = []; // true or false

var particles = [];

function setup() {
  createCanvas(400, 400);

  for (var i = 0; i < 100; i++) {
    particles.push(new Particle(random(width), random(height)));
  }
}

function draw() {
  background(51);

  strokeWeight(4);
  for (var i = 0; i < attractors.length; i++) {
    if (attractorsKind[i]) {
      stroke(0, 255, 0);
    } else {
      stroke(255, 0, 0);
    }
    point(attractors[i].x, attractors[i].y);
  }

  for (var i = 0; i < particles.length; i++) {
    for (var j = 0; j < attractors.length; j++) {
      particles[i].attracted(attractors[j], j, attractorsKind[j]);
    }

    particles[i].update();
    particles[i].show();
  }
}

function mousePressed() {
  attractors.push(createVector(mouseX, mouseY));
  attractorsKind.push(mouseButton === LEFT); // true or false
}

// ===================================================

function Particle(x, y) {
  this.pos = createVector(x, y);
  this.vel = createVector();

  this.acc = createVector();
  this.maxspeed = 6;

  this.update = function () {
    this.vel.add(this.acc);
    this.vel.limit(this.maxspeed);
    this.pos.add(this.vel);
    this.acc.mult(0);
  };

  this.show = function () {
    stroke(255);
    strokeWeight(4);
    point(this.pos.x, this.pos.y);
  };

  this.attracted = function (target, j, kind) {
    //var dir = target -this.pos
    var force = p5.Vector.sub(target, this.pos);
    var dsquared = force.magSq();
    dsquared = constrain(dsquared, 5, 50);
    var G = 10;
    var strength = G / dsquared;
    force.setMag(strength);

    if (kind) {
      force.mult(1);
    } else {
      force.mult(-1);
    }
    this.acc.add(force);
  };
} //class
//

2 Likes