Check key presses faster than a game loop

I have a class called Activity

that extendsJPanel

My problem is that I want to Activity

run the game loop (update its fields and GUI, etc.) every 1000ms, but always check for keystrokes (for a response).

private final BitSet keys = new BitSet(256);
...

public void keyPressed(final KeyEvent e) {
    keys.set(e.getKeyCode()); 
}

public void keyReleased(final KeyEvent e) {
    keys.clear(e.getKeyCode());
}

...

public void actionPerformed(ActionEvent e) {
  processKeys(); // Checks keys
  processData(); // Main game loop
  repaint();     // Draws game components
}

      

Currently, the class stores keystrokes in BitSet

, and every actionPerformed()

1000ms , looks at the pressed keys (for example, moves the player's position to the right of the arrow to the right), processes the main game material (for example, ending the game if the border is hit), and redraws the screen in this okay.

The problem is that I have to press a key before starting the timer for it to be detected, as otherwise it will be removed from BitSet

by the time it is called processKeys()

. I still want the game loop to run every 1000m.

I have considered either

  • Creation of 2 simultaneous timers - 1000ms for the game loop, 1ms for the analysis of key presses.
  • Setting the timer I have to 1ms and using a class field to keep track of timer firing. The control key presses each fire and starts the game loop / redraw whenfires % 1000 == 0

I'm not sure if # 1 is causing performance issues or causing inconsistent timers, and I'm sure # 2 is unreliable as when I tried this, often the field never succeeded 1000 or 2000, etc. p>

What solution?

+3


source to share


2 answers


As you seem to have found that with the delay between key press and long processing, it is possible that the key will be removed from yours BitSet

before they are processed.

Instead you have two BitSet

s, one for pressed and one for released keys, after you have processed the keys, remove all items in "released keys" from the set of "pressed keys", reset set and continue with "release keys".



This assumes, of course, that you want to process ANY key entered during the 1 second delay between process loops.

Another choice might be to actually handle the key events in real time, applying their effects to some "state of change" that can be applied to the actual model when a process loop occurs, but is the same value

+3


source


You can create a thread that updates the GUI every second and use the code

Thread.sleep(1000);

      

to pause the thread for a second.

If you are new to oracle page rendering this is a good place to start: https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html



For example:

public class GUIThread implements Runnable extends Activity{

    public void run() {
        repaint();
        Thread.sleep(1000);
    }
}

      

...

new Thread(new GUIThread()).start();

      

-1


source







All Articles