How to make keyPressed work inside a while loop

Hi guys,I’m working on a project and I need to detect keypressed inside a while loop. Basically there is going to be couple of while loops and depending on the key pressed, the program will come out from the while loop.

I’ll include the piece of code I’m testing on to get started.

char question = 'a';
boolean one = false;
boolean two = false;




void setup() {
  size(400, 400);
}

void draw() {
  while (question == 'a') {
    if (one == true) {
      question = 'b';
    }
  }
  println("I'm out");
}

void keyPressed() {
  if (key == 'a') {
    one = true;
  }
  if (key == 'b') {
    two = true;
  }
}

Unfortunately, what you are asking is not possible (I think) as keyPressed is only checked between frames being drawn. However, you could just use an if statement inside draw; the loop is already being done for you!

e.g.

char question = 'a';

void setup() {
  size(400, 400);
}

void draw() {
  if(question == 'a') {
    //question a stuff
  }else{
    //question b stuff
  }
}

void keyPressed() {
  if (key == 'a' || key == 'b') {
    question = key;
  }
}

Hi Yamin,

You need to work with the notion of state.
The draw() is already your while loop.

See the code below:

int state;

void setup() {
  size(400, 400);
  state = 0;
}

void draw() {
  if (state == 0) {
    background(255, 0, 0);
  } else if (state == 1) {
    background(0, 255, 0);
  } else {
    background(20);
    println("I'm out");
    noLoop();
  }
}

void keyPressed() {
  if (key == 'a') {
    state = 0;
    return;
  }
  if (key == 'b') {
    state = 1;
    return;
  }
  state = 2;
}

You get a red background by clicking a, a green one by clicking b and a black one with anything else. Also not that when you click on something else you can’t press a and b anymore.

2 Likes

Alternatively, if you only want the question a/b stuff to run once, you could use noLoop() and then call draw or a function you have written when the right key is pressed.

1 Like

I think this is cheating, so not recommended.
But I will leave as reference:

void setup() {
  size(400, 400);
  background(0);
  text("press 'a' to start", 20, 20);
}


void draw() {

  while ( !keyPressed ) {
    if (key == 'a') {
      background(#ffaaaa);
      text("question 1", 20, 20);
    }
    if (key == 'b') {
      background(#aaaaff);
      text("question 2", 20, 20);
    }
    noLoop();
  }
}

void keyReleased() {
  loop();
}

A different (maybe more reliable) approach could be:

void setup() {
  size(400, 400);
  colorMode(HSB,100);
}

int number = 0;
String quest[] = {"question 1\nsome question",
                  "question 2\nanother question",
                  "finished!"};

void draw() {
  background( color(random( 100 ), 50, 50) );
  text ( quest[number], 20, 20);
  noLoop();
}

void keyPressed(){
  loop();
  if(key == 'a' && number == 0) number++;
  if(key == 'b' && number == 1) number++;
}

Thanks guys for the response, basically what I have to do is display a question on the screen, which might have multiple answers the students have to press the correct numbers in-order to go forward. So the code has to loop at that question until the student answers correctly.

Hi Yamin,

You need to handle that in the keyPressed() function in the code I posted.

What you want to do is check if the answer is correct every time a key is pressed. If the answer is correct then you change the state (aka you go to the next question). Otherwise you don’t and the same question stays.

You can check out this thread, the logic is the same: Quiz game - need help

This is the key thing to understand. Processing is already designed to make things like this easy if you treat draw like your while loop. After the end of every draw (every frame), all the interaction functions – mouseDragged(), keyPressed(), keyReleased(), etc. – are checked. So I recommend following @jb4x’s advice and do your checking there.

If you have a lot of different states, then write a simple state machine by turning most of your draw loop into a switch statement.

This also makes it simple to prototype your state machine before writing any of the code. For example, here is a simple state machine that asks questions and displays answers until a score is reached, then it displays the end screen.

char state = 'q';
int score = 0;
int max = 3;

void draw() {
  switch(state) {
  case 'q':
    question();
    break;
  case 'a':
    answer();
    break;
  case 'e':
    end();
    break;
  default:
    question();
  }
}

void question() {
  background(255, 0, 0);
}

void answer() {
  background(0, 255, 0);
}

void end() {
  background(0, 0, 255);
}

void score() {
  score += 1;
}

void keyReleased() {
  switch(state) {
  case 'q':
    state = 'a';
    break;
  case 'a':
    score();
    if (score < max) {
      state = 'q';
    } else {
      state = 'e';
    }
    break;
  case 'e':
    end();
    break;
  default:
    question();
  }
}

This simple sketch outline only asks three “questions”, and the “answer” is always correct – so I just press the space bar a few times and the “game” is over. But it shows me that draw is acting as a while loop, displaying my question state (red), answer state (green), or end state (blue) at the correct times. Having designed that, I can now get into the code for asking and scoring questions separately, each in its own function, without worrying about the state logic.

2 Likes