Keypressed overlapping on multiple keys

I have developed software to control a small robotic submarine with arduino and an xbox controller. The xbox is keymapped and the interface in Processing sends serial commands to the Arduino. The controls are mapped out similarly to a first person shooter (movement with left stick, camera with right stick). The problem is with multiple simultaneous inputs. For example, if I am moving forward (left stick forward) then use adjust heading with the right stick without releasing the left stick, the command for right stick will continue occurring until the left stick is released or changed to a new direction.

How can I set a precedence for certain commands, so that if their key/stick is still pressed when a lower precedence key/stick is released, it will automatically resume the higher precedence command?

  // Key mappings for directional controls
  if (keyPressed && key == 'z') {  // Constantly repeats while true
    msg = 0;
  } else if (keyPressed && key == 'x') {
    msg = 1;
  } else if (keyPressed && key == 'w') {
    msg = 2;
  } else if (keyPressed && key == 'a') {
    msg = 3;
  } else if (keyPressed && key == 's') {
    msg = 4;
  } else if (keyPressed && key == 'd') {
    msg = 5;
  } else if (keyPressed && key == '8') {
    msg = 6;
  } else if (keyPressed && key == '4') {
    msg = 7;
  } else if (keyPressed && key == '5') {
    msg = 8;
  } else if (keyPressed && key == '6') {
    msg = 9;
  } else {
    msg = 50;
  }
    port.write(msg);
    powerKnob.setValue(power); 
}

  //Power adjustment mappings
void keyPressed() { // Only logs keystroke once, not a true/false like above.
  if (key == 'i') {
    msg = 10;
  } else if  (key == 'o') {
    msg = 11;
  } else if  (key == 'p') {
    msg = 12;
  } else if  (key == 'l') {    // Toggle lights button
    msg = 13;
  } 
  port.write(msg);
}

In this situation the keys inside the if statement are my focus. Z, x, w, a, s, and d (movement commands) should take precedence over 8, 4, 5, and 6 (camera commands). The list of else-if statements is my big problem, how would you suggest structuring it?

Tagged:

Answers

  • edited August 2017 Answer ✓

    I would suggest not using the keyPressed boolean at all. Instead, use keyPressed() and keyReleased() (the functions) to track which keys are being held down at any given point in time. You can store this information in a boolean array.

    char[] keys_to_check = { 'x', 'a', 's', 'd', 'w' };
    boolean[] keys_down = new boolean[keys_to_check.length];
    
    void keyPressed(){
       copeWithKeys(true); // TRUE MEANS KEY PRESSED
    }
    
    void keyReleased(){
      copeWithKeys(false); // FALSE MEANS KEY NOT PRESSED
    }
    
    void copeWithKeys(boolean state){
      for( int i = 0; i < keys_to_check.length; i++){
        if( keys_to_check[i] == keyCode ){ keys_down[i] = state; }
      }
    }
    

    Then in draw you can check which keys are currently pressed in order, and send the first message that has the right importance. If you put the keys in order of importance in keys_to_check, then the first one that is pressed can define the value to send and you can exit your loop with a break;.

  • Thank you! This is fantastic, and exactly what I need. I am a beginner and it has already been several weeks since I wrote my code and only in the past few days been able to test how the controls feel so going in to make changes has been a crash course.

  • edited August 2017

    One gotcha to watch out for:

    Depending on how your controller keys are mapped, don't forget that some keyboard interfaces have a limit on simultaneous keypresses. If you mash eight buttons more or less simultaneously, you may only get 4-5 down events, then another 3 up events, etc....

    If you are only expecting e.g. 3 simultaneous keypresses you are fine, but keep an eye out for that in debugging if you start getting weird results.

Sign In or Register to comment.