/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.KX$-Cqoozjo/rev.13
 * 
 * authors: 
 *   GoToLoop
 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 
/** 
 * Rotating Cars (v2.03)
 * by  TFGuy44 (2013/Aug)
 * mod GoToLoop
 * 
 * http://forum.processing.org/topic/adding-in-acceleration-and-momentum
 * http://studio.processingtogether.com/sp/pad/export/ro.9NBw8x3YGExwu/latest
 */
static int gw, gh;
static float x, y, z, v;
static boolean north, south, west, east;
final static float SPD = .2, ROT = .1, ACCEL = .98;
final static short CARS = 50;
final Car[] cars = new Car[CARS];
void setup() {
  size(640, 480);
  smooth();
  gw = width;
  gh = height;
  x = gw>>1;
  y = gh>>1;
  for ( int i = 0; i != CARS; cars[i++] = new Car() );
}
void draw() {
  background(0300);
  for (Car c: cars)  c.go();
  update();
  display();
}
void keyPressed() {
  setKeys(keyCode, true);
}
void keyReleased() {
  setKeys(keyCode, false);
}
static final void setKeys(int k, boolean decision) {
  if      (k == UP    | k == 'W')   north = decision;
  else if (k == DOWN  | k == 'S')   south = decision;
  else if (k == LEFT  | k == 'A')   west  = decision;
  else if (k == RIGHT | k == 'D')   east  = decision;
}
static final void update() {
  v += (north? SPD : 0) - (south? SPD : 0);
  z += (east?  ROT : 0) - (west?  ROT : 0);
  x = (x + gw + cos(z)*v) % gw;
  y = (y + gh + sin(z)*v) % gh;
  v *= ACCEL;
}
void display() {
  translate(x, y);
  rotate(z);
  noStroke();
  fill(-1); 
  rect(-20, -20, 40, 40);
  stroke(0);
  noFill();
  triangle(-15, -15, 15, 0, -15, 15);
  resetMatrix();
}
final class Car {
  boolean a, b, c;
  float x, y;
  float z = random(TWO_PI), v = random(5);
  final color k = (color) random(#000000);
  Car() {
    x = width>>1;
    y = height>>1;
  }
  void go() {
    update();
    display();
  }
  void update() {
    if (random(1) > .98)   a = !a;
    if (random(1) > .95)   b = !b;
    if (random(1) > .95)   c = !c;
    if (a)   v += SPD;
    z += (b? ROT : 0) - (c? ROT : 0);
    x = (x + width  + cos(z)*v) % width;
    y = (y + height + sin(z)*v) % height;
    v *= ACCEL;
  }
  void display() {
    translate(x, y);
    rotate(z);
    noStroke();
    fill(k); 
    rect(-10, -10, 20, 20);
    stroke(0);
    noFill();
    triangle(-8, -8, 7, 0, -8, 8);
    resetMatrix();
  }
}