Changing target positions of vehicles

In this project, I have used the text to point function to create vehicles which exhibit the seek, arrive and flee behaviours. Currently, the vehicles form the word ‘SWIMMY’ which is the start and target position. On clicking, I want the vehicles to form another word, say, fish. How can I change the target position of the vehicles on clicking the mouse or a button? I tried using a mouse clicked function in the sketch file but it did not work.
I have been struggling with figuring this out, so it would mean a lot if you could help me.

The sketch file:

var font;
var vehicles= [];
let water;
let img;






function preload(){
 font = loadFont ('AvenirNextLTPro-Demi.otf');
  //img = loadImage ('swimmy fish-1.png'); //this was perhaps to use the image of swimmy instead of the elipses
}

function setup(){
  noCursor();
  
 createCanvas(1200, 500);
  water = createVideo('Water.mp4'); 
  //links the term 'water' to the video
  water.hide();  //hides the extrarandom video plaing at the bottom
  water.autoplay(); //autoplays the video on loading of sketch
  water.loop();

  textFont(font); //all settings to make text appear
  // textSize(192);
  // fill(255);
  // noStroke();
   //text('SWIMMY',100,0); //all this text was to make the text on which the points could be made but now that we have points, we dont need them

  
  
  
   var points = font.textToPoints('S w i m m y',100,300,192); 
  //this creates a variable that is the points converted from text. 100 and 300 are the positions on x ad y and 192 is the size of the font
  
 
  for (var i = 0; i<points.length;i++){
    var pt = points[i];
    // stroke(255);
    // strokeWeight(10);
    // point(pt.x,pt.y); //all these three contol the way the points will look but I have changed those to the elipses so i dont need these
    var vehicle = new Vehicle(pt.x , pt.y);
//now that there is an intro of a new variable vehicle, instead of drawing points in set up, they can be represented here
    vehicles.push(vehicle);
    //so now there is a new vehicle for every point isolated in the console
    
    //** everytime a new vehicle is introduced, it must be added in the index.html section
   
  }
}
  
  
function fish(x,y){
  fill(random(192,192,192),random(255,129,129));
  ellipse(x+14,y,10,12);
  fill(random(192,192,192),random(255,129,129));
  ellipse(x,y,25,15);
  
}
 



   function mouseClicked() {
      var points = font.textToPoints('The Fish',100,300,180); 
 
  }

   //water.loop(); // set the video to loop and start playing
 //}
//the above function only makes sense if i want to control when i want the video to start playing
    
 



function draw(){
  background(0,119,190);
  image(water, 0, 0); // draw the video frame to canvas
  //filter(GRAY);
  //image(water, 150, 150);
  //water.loop();
   
 
  noStroke();
    fill(random(0,0,0), random(105,105,105));
  ellipse(mouseX+14,mouseY,10,12);
  fill(random(0,0,0),random(105,105,105));
  ellipse(mouseX,mouseY,25,15)
   
  
  for (var i = 0; i< vehicles.length; i++){ //noprotect
  var v = vehicles[i];
    v.behaviours(); //this would make use of the behaviours we have put in the vehicles.js
    v.update();
    v.show();
  }
}

The vehicle.js file:

function Vehicle(x,y){ //constructor function to make vehicle ojects
  //this.pos = createVector(x,y); //is this is on, the points srat possition will be on swimmy itself
 this.pos = createVector(random(width),random(height)); //the vehicles need a starting position which will be a vector
 //this.vel = createVector();
 this.vel = p5.Vector.random2D(); //giving each a random veocity
 this.acc = createVector();
 this.target = createVector(x,y); //this is the objects target position
  //each vehicles obj needs a position, a target position, a velocity and an acceleration
  this.r=8
  this.maxspeed = 10; 
  this.maxforce = 1;
}


//below the vehichle prototype is a better and more efficient way of attaching functions to objects
Vehicle.prototype.behaviours = function(){ 
 var arrive = this.arrive(this.target); 
  
 var mouse = createVector(mouseX,mouseY);
  var flee = this.flee(mouse); //to make vehicles afraid of the mouse
  
  arrive.mult(1);
  flee.mult(5);
  //here we differentiate the different forces, so the flee force is much more forcefull than the arrive force
  
  this.applyForce(flee);
  this.applyForce(arrive);
  //applyForce function doesnt actually exist so it has to be written below
  
  //**if we needed only one behaviour, for example the seek function then that would be it. but here were assuming that there will be more than one behaviour which is why we have the prototype behaviours
}



Vehicle.prototype.applyForce = function(f){
this.acc.add(f); //so if multiple forces are at play, we could add all of them in the acceleration and hence all the animations must start by 0
}



Vehicle.prototype.update = function(){ //way of attaching functions to objects
 this.pos.add(this.vel);
  this.vel.add(this.acc);
  //basic physics idea of acc changing velocity and velocity changing acceleration
  this.acc.mult(0); //this multiplies everything by 0 so that everything starts from 0 for the applyForce function to work
}




//below funtion of show to display or render the stuff we have said so far
Vehicle.prototype.show = function() {
  
   stroke(random(192,192,192),random(255,129,129));
   strokeWeight(1);
 //  point(this.pos.x,this.pos.y);//linking the vehicle to particular points and their characteristics. the this.pos. is beign brought in from the for loop in sketch.js where it is pt.x and pt.y
  
  
 // triangle(this.pos.x-5, this.pos.y+5, this.pos.x+5, this.pos.y+5, this.pos.x, this.pos.y-5); //this has made all the points into triangles. if i only say /points' the function will always create a circle.
  //image(img, this.pos.x, this.pos.y);
  fish(this.pos.x,this.pos.y); //the fish is the point
  
  
  //translate(this.pos.x, this.pos.y);
  //rotate(PI / 2.0);
}




Vehicle.prototype.arrive = function(target){
 var desired = p5.Vector.sub (target, this.pos); 
  var d = desired.mag();
  var speed = this.maxspeed;
  
if (d<100){
   speed = map(d, 0, 100, 0, this.maxspeed);
  }
  desired.setMag(speed);
  var steer = p5.Vector.sub(desired, this.vel);
  steer.limit(this.maxforce);
  return steer; 
}



Vehicle.prototype.seek = function(target){
 var desired = p5.Vector.sub (target, this.pos); //this line is subtracting the vector points from position to target, you subtract the two vectors 
  //desired vel is always its aximum speed
  desired.setMag(this.maxspeed);
  var steer = p5.Vector.sub(desired, this.vel); 
  //since steering= desired vel- current vel
  steer.limit(this.maxforce);// so the steering isnt that powerful
  return steer; //the idea is to calculate that force and return it to be applied in seek
}



Vehicle.prototype.flee = function(target){
 var desired = p5.Vector.sub (target, this.pos); 
  var d = desired.mag();
  if (d<50){
  desired.setMag(this.maxspeed);
  desired.mult(-1); //,aking the vehicle move in the away direction
  var steer = p5.Vector.sub(desired, this.vel);
  steer.limit(this.maxforce);
  return steer; //the idea is to calculate that force and return it to be applied in seek
  }else{
  return createVector(0,0);
  }
  //the point of adding the if and else is to control when and how much the vehicles are afraid of the mosue
}

1 Like

upon mouseClick clear vehicles and fill it anew
using the for loop like in setup()

or instead of saying var vehicle = new Vehicle(pt.x , pt.y); just give them a new target position

 var points = font.textToPoints('FISH',100,300,192); 

  //this creates a variable that is the points converted from text. 100 and 300 are the positions on x ad y and 192 is the size of the font
  
 
  for (var i = 0; i<points.length;i++){
    var pt = points[i];
    // stroke(255);
    // strokeWeight(10);
    // point(pt.x,pt.y); //all these three control the way the points will look but I have changed those to the ellipses so i don't need these
    var vehicle = new Vehicle(pt.x , pt.y);
//now that there is an intro of a new variable vehicle, instead of drawing points in set up, they can be represented here
    vehicles.push(vehicle);
    //so now there is a new vehicle for every point isolated in the console
    
    //** every time a new vehicle is introduced, it must be added in the index.html section
   
  }

Hi Chrisir, thank you very much for your reply.
In your response you have said “instead of saying var vehicle = new Vehicle(pt.x , pt.y); just give them a new target position”
This is what I am aiming to do, however, I am unable to figure out how to write this change into the code. In the sketch.js file, I tried writing

function mouseClicked() {
  var points = font.textToPoints('FISH',100,300,180); 
 }

but on clicking the mouse, there is no change.
The issue I am facing is how to express the logic in code and getting it to work.

I am still learning P5js, so sometimes it is a little difficult for me to navigate the syntax

Never mind

How is it when you just use the lines I initially posted

The way i Used your code was like this in addition to my earlier code:

  function mouseClicked() {
  var points = font.textToPoints('FISH',100,300,192); 

  //this creates a variable that is the points converted from text. 100 and 300 are the positions on x ad y and 192 is the size of the font
  
 
  for (var i = 0; i<points.length;i++){
    var pt = points[i];
    // stroke(255);
    // strokeWeight(10);
    // point(pt.x,pt.y); //all these three control the way the points will look but I have changed those to the ellipses so i don't need these
    var vehicle = new Vehicle(pt.x , pt.y);
//now that there is an intro of a new variable vehicle, instead of drawing points in set up, they can be represented here
    vehicles.push(vehicle);
    //so now there is a new vehicle for every point isolated in the console
    
    //** every time a new vehicle is introduced, it must be added in the index.html section
   
  }
 
  }

So now what is happening is that on clicking, the word ‘fish’ is forming on top of the swimmy instead of the word swimmy breaking to form fish.