Temporarily slow down speed in Processing

Viewed 347

For our school assignment, we are tasked to

Alter the Two Car objects program from the tutorial so that every time the cars pass by each other, the cars slow down to 33% of their speed and an orange vertical line is drawn between centers of the two cars to indicate that the drivers are making eye contact.

However, whenever I try to change the speed using if-else conditionals or other methods, the speed change becomes permanent. Other times, the speed does not change at all. I only managed to do the orange vertical line.

Here's an image of what I currently have: Screenshot of the program

Here's what it should be doing: Video

Here is the code:

// Example: Two Car objects
Car myCar1;
Car myCar2; // Two objects!

void setup() {
  size(200,200);
  // Parameters go inside the parentheses when the object is constructed.
  myCar1 = new Car(color(255,0,0),0,100,2); 
  myCar2 = new Car(color(0,0,255),0,10,1);
}

void draw() {
  background(255);
  myCar1.drive();
  myCar1.display();
  myCar2.drive();
  myCar2.display();
  stroke(255,128,0);
  line(myCar1.xpos,myCar1.ypos,myCar2.xpos,myCar2.ypos);
}

// Even though there are multiple objects, we still only need one class. 
// No matter how many cookies we make, only one cookie cutter is needed.
class Car { 
  color c;
  float xpos;
  float ypos;
  float xspeed;

  // The Constructor is defined with arguments.
  Car(color tempC, float tempXpos, float tempYpos, float tempXspeed) { 
    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
    xspeed = tempXspeed;
  }

  void display() {
    stroke(0);
    fill(c);
    rectMode(CENTER);
    rect(xpos,ypos,20,10);
  }

  void drive() {
    xpos = xpos + xspeed;
    if (xpos > width) {
      xpos = 0;
    }
  }
}

Any help is greatly appreciated. Thanks in advance.

  [1]: https://i.stack.imgur.com/q0hAX.png
  [2]: https://youtu.be/dIGr9RprfoE
1 Answers

I'd start by braking the task down:

Alter the Two Car objects program from the tutorial so that every time the cars pass by each other, the cars slow down to 33% of their speed and an orange vertical line is drawn between centers of the two cars to indicate that the drivers are making eye contact.

How do you determine if the cars pass by each other ? Luckily, in this simple example the movement is one dimension: on the X axis. You can simply compare the xpos of each car

e.g.

if(myCar1.xpos == myCar2.xpos){
  println("slow down to 33% and draw orange line between cars");
}

You do need to be careful you're working with floating point numbers so the odds of the numbers matching perfectly are much slimmer than if comparing integers for example.

You could for example make use of the dist() function which computes the Euclidean distance between two pairs of points, however the cars don't move on x,y, just on x, so you could save a bit of computing power by simply computing abs()olute difference between the two x positions.:

float absdiff = abs(myCar1.xpos - myCar2.xpos);

Instead of comparing if the absolute distance you could use a threshold value. Let's say the cars are less than 20px apart, then they're considered to be passing each other. This will result in a less jarring simulation, since checking a single value (distance == 0) will happen at most for a split second(frame) while a range(distance < threshold) will be true for longer.

With that out of the way it's matter of drawing the line (which you already do) and slowing the speed down to 33%;

The catch is that you'll need an extra property for the Car class to remember the original speed so you can easily restore to, otherwise values become relative and keep decreasing. Otherwise, each time the cars pass by, both would slow down to a stop. You can use the extra variable to simply set the current speed either to this initial value, when the cars no longer pass each other or to 33% of this initial values otherwise:

// Example: Two Car objects
Car myCar1;
Car myCar2; // Two objects!

// anything smaller than this distance means the cars pass each other
float passbyThreshold = 20;

void setup() {
  size(600,200);
  strokeWeight(3);
  // Parameters go inside the parentheses when the object is constructed.
  // speed up car 1 for testing to increase the odds of passing by
  myCar1 = new Car(color(255,0,0),0,100,4); 
  myCar2 = new Car(color(0,0,255),0,10,1);
}

void draw() {
  background(255);
  
  myCar1.drive();
  myCar1.display();
  myCar2.drive();
  myCar2.display();
  // compute 1D distance between cars (abs() means it doesn't matter which one's faster)
  float absdiff = abs(myCar1.xpos - myCar2.xpos); 
  text("distance:" + absdiff, 10, height-15);
  // if the cars are close enough to be passing by
  if(absdiff < passbyThreshold){
    // slow down the cars to 33% of their speed
    myCar1.slowDown();
    myCar2.slowDown();
    // draw the orange line between the centres
    stroke(255,128,0);
    line(myCar1.xpos,myCar1.ypos,myCar2.xpos,myCar2.ypos);
  }else{
    myCar1.revertSpeed();
    myCar2.revertSpeed();
  }
}

// Even though there are multiple objects, we still only need one class. 
// No matter how many cookies we make, only one cookie cutter is needed.
class Car { 
  color c;
  float xpos;
  float ypos;
  
  // original speed
  float ospeed;
  
  float xspeed;

  // The Constructor is defined with arguments.
  Car(color tempC, float tempXpos, float tempYpos, float tempXspeed) { 
    c = tempC;
    xpos = tempXpos;
    ypos = tempYpos;
    xspeed = tempXspeed;
    // store original speed so xspeed can be restored to it
    ospeed = tempXspeed;
  }

  void display() {
    stroke(0);
    fill(c);
    rectMode(CENTER);
    rect(xpos,ypos,20,10);
    text(xspeed,xpos - 10,ypos + 20);
  }

  void drive() {
    xpos = xpos + xspeed;
    if (xpos > width) {
      xpos = 0;
    }
  }
  
  void slowDown(){
    // set speed to 33% of the original speed
    xspeed = ospeed * .33;
  }
  
  void revertSpeed(){
    // revert speed to the original value
    xspeed = ospeed;
  }
}
Related