Simulating rear lights of a car

Hi there,
I wrote this messy code intended to simulate the behaviour of the rear lights of a car:

//introducing variables
//n manages the timing for left and right arrows
int n;

//m and on manage the timing for emergency arrows
int m;
boolean on;


void setup() {
  //I'm forced to slow down frameRate to have an appreciable result
  frameRate(20);

  size(640, 360);
  background(0);

  //assigning initial values to variables
  n = 0;
  m = 0;
  on = false;
}


void draw() {

  fill(255, 215, 0);
  noStroke();

  //calling the various functions
  leftArrow();
  rightArrow();
  emergencyArrow();
  brake();

  //creating rectangles to make the arrows seem discontinuous
  fill(0);

  for (int i = 0; i < 30; i++) {
    rect(i * width/30, height/2-10, 2, 20);
  }

  //increasing variables
  n++;
  m += 2;
}

//a function to show a progressive left arrow
void leftArrow() {
  //if left arrow is pressed
  if (keyCode == LEFT) {
    //AND on is true
    if (on == true) {
      //I draw the rectangles 
      //modulo operator is useful to introduce different time lapses
      if (n % 10 == 0) {
        rect(9 * width/30 - width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 1) {
        rect(8 * width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 2) {
        rect(7 * width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 3) {
        rect(6 * width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 4) {
        rect(5 * width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 5 ) {
        rect(4 * width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 6) {
        rect(3 * width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 7) {
        rect(2 * width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 8) {
        rect(width/30, height/2-10, width/30, 20);
      } else if (n % 10 == 9) {
        rect(0, height/2-10, width/30, 20);
      }

      //then a condition to make the rectagles disappear is introduced
      if (n > 11) {
        n = 0;
        background(0);
      }
    }
  }
}

//a function to show a progressive right arrow
void rightArrow() {
  //if right arrow is pressed
  if (keyCode == RIGHT) {
    //AND on is true
    if (on == true) {
      //I draw the rectangles 
      //modulo operator is useful to introduce different time lapses
      if (n % 10 == 0) {
        rect(2 * width/3, height/2-10, width/30, 20);
      } else if (n % 10 == 1) {
        rect(2 * width/3, height/2-10, 2 * width/30, 20);
      } else if (n % 10 == 2) {
        rect(2 * width/3, height/2-10, 3 * width/30, 20);
      } else if (n % 10 == 3) {
        rect(2 * width/3, height/2-10, 4 * width/30, 20);
      } else if (n % 10 == 4) {
        rect(2 * width/3, height/2-10, 5 * width/30, 20);
      } else if (n % 10 == 5 ) {
        rect(2 * width/3, height/2-10, 6 * width/30, 20);
      } else if (n % 10 == 6) {
        rect(2 * width/3, height/2-10, 7 * width/30, 20);
      } else if (n % 10 == 7) {
        rect(2 * width/3, height/2-10, 8 * width/30, 20);
      } else if (n % 10 == 8) {
        rect(2 * width/3, height/2-10, 9 * width/30, 20);
      } else if (n % 10 == 9) {
        rect(2 * width/3, height/2-10, 10 * width/30, 20);
      }

      //then a condition to make the rectagles disappear is introduced
      if (n > 11) {
        n = 0;
        background(0);
      }
    }
  }
}

//a function to show two blinking arrows
void emergencyArrow() {
  //introducing a timer
  int t = m % 50;

  //if up arrow is pressed
  if (keyCode == UP) {
    //AND on is true
    if (on == true) {
      //I draw some blinking rectangles
      if (t < 25) {
        fill(255, 215, 0);
        rect(0, height/2 - 10, width/3, 20);
        rect(2 * width/3, height/2 - 10, width/3, 20);
      } else {
        background(0);
      }
    }
  }
}

//a function to show brake lights
void brake() {
  noStroke();
  //if down arrow is pressed
  if (keyCode == DOWN) {
    //I draw all the red rectangles
    fill(255, 0, 0);
    rect(width/3, 0, width/3, 20);
    rect(0, height/2 + 10, width/3, 20);
    rect(2 * width/3, height/2 + 10, width/3, 20);
  } 

  //introducing the condition to make the lights switch off
  if ((keyCode == DOWN) && (keyPressed == false)) {
    background(0);
  }
}

//changing the boolean to its opposite to "arm" the switches
//if I press again the same keys, the arrows are switched off
void keyPressed() { 
  if ((keyPressed == true) && ((keyCode == UP) || (keyCode == RIGHT) || (keyCode == LEFT))) {
    on = !on;
    background(0);
  }
}

Please excuse the headhache…
What’s the way to keep left or right arrow drawing while pressing the brake key?
What’s the way to keep emergency arrow blinking while pressing the brake key?

Hello,

Sharing an example that will work with multiple key presses:

Example Code < Click here to open!
// Simulate Car Lighting
// v1.0.0
// GLV 2020-06-07

boolean brake = false; 
boolean toggle = false; 
boolean signalLeft = false; 
boolean emerg = false; 

void setup() 
	{
  size(400, 600);
  textSize(24);
	}

void draw() 
	{
  background(0);
  
  if (frameCount %10 == 0)
    toggle = !toggle;
    
  if(signalLeft && !emerg)
    {
    if(toggle)
      {
      text("Signal", 100, 100);
      }
    }  
	
  if(brake && !emerg)
    {
    text("Brake", 100, 200);
    } 
    
  if(emerg)
    {
    text("Emergency", 100, 300);
    }      
  }
  
 void keyPressed() 
   {
   //if (keyCode == LEFT) signalLeft = !signalLeft; //If key held down it toggled to often!
   if (keyCode == DOWN) brake = true;
   if (keyCode == UP) emerg = true;
   }
      
void keyReleased() 
  {
  if (keyCode == LEFT) signalLeft = !signalLeft;  
  if (keyCode == DOWN) brake = false;
  if (keyCode == UP) emerg = false;
  } 

I removed all the finishing touches (shapes and colors) I had for this example.

The logic will need some more work… just getting you started.

There are other ways to handle multiple key presses.

Have fun!

:)

Awesome!

Some quick notes:

for the original code, anytime you write
if(statement == true)
it’s really equivalent to saying
if(statement)
Trust me, I used to make statements like that all the time.

For the solution code
You could also replace
toggle = !toggle;
with
toggle ^= true;

Not that makes it any better, or any worse, but sometimes it can be handy (especially when you get long variable names).

Again for the solution code:
Here, it might actually be a good idea to make use of if else statements. You could start with the if(emerg) statment, then wrap the brake and signal statements into an else statement. : )

If you need any help adapting the latter code into something with graphical interface like the original code, I’d be more than happy to jump in and help : )

Hope this helps!

If you need any help adapting the latter code into something with graphical interface like the original code, I’d be more than happy to jump in and help : )

Feel free to fork my repo on GitHub:

Th3cG/blinking-arrows

(this would also give me a better understanding of how GitHub works)

Um…here’s the thing, I know how to download things from Github (provided the author was kind enough to make an understandable README), and I know how to upload things to there for the sake of having a backup file. But…I really really suck at uploading things there in a form that other people can actually use. So, I’ll just send it here:

boolean leftArrow=false, rightArrow=false, emerg=false, brake=false;
boolean pressingDown=false; //extra precaution, you'll see why in a bit :)

int blinkerTimer=0;
int emergTimer=0;

void setup() {
  frameRate(20);
  
  size(640,360); noStroke();
}

void draw() {
  background(0);
  
  leftArrow();
  rightArrow();
  brake();
  emergencyArrow();
  
  blinkerTimer=(blinkerTimer+1)%11; //increment blinker timer by 1 and modulo by the duration of the blinker animation (which in this case is 11)
  emergTimer=(emergTimer+1)%24; //do the same for emergency timer, but this time the duration is 24
}

void leftArrow() {
  if(leftArrow) {
    fill(255,215,0); stroke(0);
    for(int n=0;n<blinkerTimer;n++) {
      rect(0.3*width-n*width/30,height/2-10,width/30,20);
    }
  }
}

void rightArrow() {
  if(rightArrow) {
    fill(255,215,0); stroke(0);
    for(int n=0;n<blinkerTimer;n++) {
      rect(2*width/3+n*width/30,height/2-10,width/30,20);
    }
  }
}

void emergencyArrow() {
  if(emerg && emergTimer<12) {
    fill(255,215,0); stroke(0);
    for(int n=0;n<10;n++) { //unlike with the blinkers, the emergency arrows will either show all of the rectangles, or none of them
      rect(2*width/3+n*width/30,height/2-10,width/30,20);
      rect(0.3*width-n*width/30,height/2-10,width/30,20);
    }
  }
}

void brake() {
  if(brake) {
    fill(255,0,0);
    rect(0,height/2+10,width/3,20);
    rect(2*width/3,height/2+10,width/3,20);
    rect(width/3,0,width/3,20);
  }
}

void keyPressed() {
  if(keyCode==UP) { brake=true; } //when holding down "down", the brakes are on
  if(keyCode==DOWN && !pressingDown) {
    emerg^=true;                  //toggle the emergency arrows
    if(emerg) {                   //if emergency blinkers are on,
      leftArrow=rightArrow=false; //deactivate the normal blinkers
      emergTimer=0;               //reset the emergency timer
    }
    pressingDown=true;
  }
  
  //now I can explain the whole "pressing down" thing.  Essentially, the keyPressed function is called anytime the user presses a key.  However, it's
  //also called when they spam a key.  You might notice that if you press and hold the 'f' key when typing something, it'll type f once, then stop, then
  //spam the letter f until you let go.  Essentially, that spamming motion is considered a key press.  The use of the boolean "pressingDown" detects anytime we press
  //down, but filters out the spams.  Unlike keyPressed, keyReleased does not activate upon spamming, only when a key is actually truly released.
  //pressingDown will become true when down is pressed, and false when it is released.  In the above code, we tell the program to only accept keyPressed instances if
  //pressingDown was previously false, otherwise it's just spam. :)
}

void keyReleased() {
  if(keyCode==UP) { brake=false; } //when not holding down "down", the brakes are off
  if(keyCode==DOWN) { pressingDown=false; }
  
  if(keyCode==LEFT  && !emerg) { leftArrow^=true; rightArrow=false; blinkerTimer=0; } //toggle the left blinker, turn off the right blinker, reset the blinker timer
  if(keyCode==RIGHT && !emerg) { leftArrow=false; rightArrow^=true; blinkerTimer=0; } //toggle the right blinker, turn off the left blinker, reset the blinker timer
  
  //(note: it's important that emerg is false, since the blinkers cannot turn on when we have the emergency lights on)
  //(note: the blinker timer should always be reset any time a blinker turns on.  Blinkers can only ever turn on in the above block of code.)
}

I should note, I did this all from scratch. I mean, I used your original code as a template for what’s supposed to happen, and I used both yours and glv’s code as guidance to make sure I was on the right path, but none of them were really compatible with what (in my completely subjective opinion) seemed to be the most robust way to go about this.

Also, I strongly recommend you read that part about the “pressingDown” variable. Full disclaimer, I didn’t learn that myself, I learned it from other people on this website over the years.

@Math_Machine thank you for the solution.
OT: I probably didn’t write an understandable README file :stuck_out_tongue:
Let me humbly and obviously suggest Shiffman’s Git and GitHub for Poets:

https://thecodingtrain.com/beginners/git-and-github/