p5: Global variables for states and time based events

So far we’ve been using inputs to trigger instant and direct changes. In many applications an input is meant to trigger a change in the internal state of the program which may not have such a immediate and straightforward mapping.
Here’s some examples:

var counterCircle = 0;
var counterSquare = 0;
var lineLength = 0;

var easingTarget = 0;
var easingCount = 0;

var colorA;
var colorB;
var betweenColor;
var colorCounter = 0;

function setup() {
  createCanvas(600, 600);
  strokeCap(SQUARE);

  //I create two colors to interpolate
  //color() is a function so it can't be called globally
  colorA = color("#ffb513");
  colorB = color("#00d6ab");

}

function draw() {
  background(255);
  noStroke();

  ///////////////////////
  //draw circle that gradually shrinks
  //counterCircle is a timer set in the keyPressed function 

  if (counterCircle > 0) {
    counterCircle--;
  }
  fill("#ff884f");

  //the countdown is remapped to the desired size of the circle
  var radius = map(counterCircle, 60, 0, 100, 0);
  ellipse(200, 300, radius, radius);


  //////////////////
  //draw square that grows for 60 frames
  if (counterSquare < 60) {
    side = map(counterSquare, 0, 60, 0, 100);
    counterSquare++;
  }

  rectMode(CENTER);
  fill("#e782ac");
  rect(400, 300, side, side);

  ///////////////
  //draw line who's length grows at every key press
  stroke("#9775a7");
  strokeWeight(10);
  line(0, 400, lineLength, 400);

  ////////////////
  //draw a line whose size "follows" a target with an easing function
  stroke("#0f82af");
  strokeWeight(10);
  //every frame add half of the distance
  easingCount += (easingTarget - easingCount) / 20;
  line(0, 200, easingCount, 200);
  //print(easingCount);

  //////////////////////
  //the rectangle's size and color change while g is pressed
  if (keyIsPressed && key == "g") {
    if (colorCounter < 1) {
      colorCounter += 0.01;
    }

  }
  //linear color interpolation: find a color between colorA -> colorB
  //based on the value of colorCounter which must be between 0 and 1
  betweenColor = lerpColor(colorA, colorB, colorCounter);
  var h = map(colorCounter, 0, 1, 1, 30);
  noStroke();
  fill(betweenColor);
  rect(300, 100, width, h);

}



function keyPressed() {

  if (key == "a") {
    counterCircle = 60;
  } else if (key == "s") {
    counterSquare = 0;
  } else if (key == "d") {
    lineLength += 30;
    if (lineLength > width) {
      lineLength = 0;
    }
  } else if (key == "f") {
    easingTarget = 600;
    easingCount = 0;
  }

  /*
  //instead of using a concatenation of conditionals
  //I can use a switch/case condition 

  switch(key) {
  case "A":
  break;

  case "S":
  break;

  case "D":
  break;
  }*/

}


function keyReleased() {

  if (key == "g") {
    colorCounter = 0;
  }
}

exercise: make a visual representation of a countdown (about 5 sec), it can be something like a loading bar, a graphic timer, a bomb’s fuse etc.
Make something happen at the end of the counter.
Let the user restart the counter with a keypress.

States

//this program is a finite state machine
//it has a definite number of states in which different operation
//happen

//I use a string to keep track of the current state
//the names are arbitrary, it could also be a number but strings are more readable
var state = "title";
var posX, posY;
var a = 0;

function setup() {
  createCanvas(600, 600);
  noStroke();
}

function draw() {
  background(255);

  if (state == "title") {
    fill("#0f82af");
    textSize(80);
    textAlign(CENTER);
    text("Keys: A S D", width / 2, height / 2);
  } else if (state == "mouseFollow") {
    posX += (mouseX - posX) / 10;
    posY += (mouseY - posY) / 10;
    fill("#ff884f");
    ellipse(posX, posY, 100, 100);
  } else if (state == "wave") {
    fill("#e782ac");
    var waveY = sin(radians(a)) * 100;
    rect(0, height / 2 + waveY, width, 30);
    a += 3;

    if (a > 360 * 2) {
      state = "title";
    }
  } else if (state == "button") {
    //check the distance to the center of the circle
    var centerDist = dist(mouseX, mouseY, width / 2, height / 2);

    //change the fill color if less than radius
    if (centerDist < 100) {
      fill("#0f82af");
      
      //if inside an the mouse is pressed back to title
      if (mouseIsPressed) {
        state = "title";
      }
    } else {
      fill("#9775a7");
    }
    //draw the ellipse
    ellipse(width / 2, height / 2, 200, 200);
  }
}



//state and certain variables are changed at specific key presses
function keyPressed() {
  
  if (key == "a") {
    posX = mouseX;
    posY = mouseY;
    state = "mouseFollow";
  } else if (key == "s") {
    state = "wave";
    a = 0;
  } else if (key == "d") {
    state = "button";
  }
}