[java] multiple key input in Java

Started by
11 comments, last by tjoink 19 years, 6 months ago
I'm posting here b/c the Java forum hasn't been replied to in 10 yrs. Take a simple Java app like this:

// MyGame.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class MyGame extends JComponent implements KeyListener {
  privates static JFrame frame;
  
  public static void main(String[] args) { 
    MyGame myGame = new MyGame();

    frame = new JFrame("My Game etc.");
    frame.addKeyListener(myGame);
    frame.setSize(640, 480);
    frame.setContentPane(myGame);
    frame.setVisible(true);
  }

  public MyGame() {
     // init JComponent
  }
  
  /* move method that's called on key presses */
  public void move(int dx, int dy) {
    System.out.println("dx = " + dx);
    System.out.println("dy = " + dy);
  }

  public void paintComponent(Graphics g) {
     // do the painting on g context 
  }
  
  /* THE IMPORTANT PART: */
  public void keyPressed(KeyEvent event) {
     switch(event.getKeyCode()) {
        case KeyEvent.VK_UP:
           move(0, -1);
           break;
        case KeyEvent.VK_DOWN:
           move(0, 1);
           break;
        case KeyEvent.VK_RIGHT:
           move(1, 0);
           break;
        case KeyEvent.VK_LEFT:
           move(-1, 0);
           break;
        default:
           break;
     }
   }

  public void keyTyped(KeyEvent event) {}
  public void keyReleased(KeyEvent event) {}
}

If you run the above example (if you can, b/c i just typed it here for simplicity), or if you have experience with Java, you'd know that when you hold down one key, and subsequently hold down another, the new key that you hold down "overrides" the old key. Therefore, using this simple method, one CANNOT have multiple arrow key input AFAIK, to control something in a game, which I am trying to do. Now that you hopefully understand the problem, you may be able to point me to a resource that I am unaware of that will help me fix this. I don't think c++ programmers have this problem when using win32, b/c I've seen a few examples and they ran as wanted without even addressing this problem. I know how to use JNI, and if it came to that I'd have to make a win32 dll that would take user input for me, but then there would be no point in using Java if I had to write win32 code still. So, I've researched this, yes, I've Googled, and found only KeyListener and KeyEvent in Java. And I don't want people to say "OMG your game sSucxks b/c Java can't handle multiple keys LOL." Kthx, for you time :)
"I study differential and integral calculus in my spare time." -- Karl Marx
Advertisement
keyPressed( KeyEvent )
if someKeyPressed
booleanKeyPressed = true

keyReleased( KeyEvent )
if !someKeyPressed
booleanKeyPressed = false
"... we should have such an empire for liberty as she has never surveyed since the creation ..."Thomas Jefferson
I see how that would work, but I have to try it first. I'm not sure if Java would see a KeyReleased event if another key is pressed when you release the key. I'll check real quick... Thanks for your help, GKW!
"I study differential and integral calculus in my spare time." -- Karl Marx
I posted a question in the Java forum not long ago, got a reply within a couple of hours.

/MineWipe
"To some its a six-pack, to me it's a support group."
OMGTHX!!1 It worked:
	public void keyPressed(KeyEvent event) {		switch(event.getKeyCode()) {			case KeyEvent.VK_UP:				// moveBlock(0, -1);				upPressed = true;				break;			case KeyEvent.VK_DOWN:				// moveBlock(0, 1);				downPressed = true;				break;			case KeyEvent.VK_RIGHT:				/// moveBlock(1, 0);				rightPressed = true;				break;			case KeyEvent.VK_LEFT:				// moveBlock(-1, 0);				leftPressed = true;				break;			case KeyEvent.VK_SPACE:			default:				break;		}		if(upPressed) {			moveBlock(0, -1);		}		if(downPressed) {			moveBlock(0, 1);		}		if(rightPressed) {			moveBlock(1, 0);		}		if(leftPressed) {			moveBlock(-1, 0);		}	}	public void keyTyped(KeyEvent event) {}	public void keyReleased(KeyEvent event) {		switch(event.getKeyCode()) {			case KeyEvent.VK_UP:				upPressed = false;				break;			case KeyEvent.VK_DOWN:				downPressed = false;				break;			case KeyEvent.VK_RIGHT:				rightPressed = false;				break;			case KeyEvent.VK_LEFT:				leftPressed = false;				break;			default:				break;		}	}


rating++; for you GKW :)
"I study differential and integral calculus in my spare time." -- Karl Marx
Quote:Original post by MindWipe
I posted a question in the Java forum not long ago, got a reply within a couple of hours.

/MineWipe


That's because they don't want anyone to know! *pulls out hair*

edit: Oh great, move my rants about Java forum into the Java forum. Everything I said was really just to test the loyalty of the GDNet Lounge people, nothing more!1

add: Oh, u don't believe me taht the Java thread never has any activity? Watch this thread stay at the top for the rest of the day. (w/o anyone replying to it ie).

[Edited by - temp_ie_cant_thinkof_name on October 18, 2004 1:23:08 PM]
"I study differential and integral calculus in my spare time." -- Karl Marx
Be careful how you use your booleans since keyevents are processed on the event thread and might not be current on another thread. Learn how to use the synchronize keyword.
"... we should have such an empire for liberty as she has never surveyed since the creation ..."Thomas Jefferson
Thanks for your humble help, GKW. rating++;
"I study differential and integral calculus in my spare time." -- Karl Marx
Also, the way you wrote it will have odd behaviour. When you press up, your block will move up, when you keep up pressed, and then press left, your block will move up again, and left.
It's good practice to execute code based on the keypressed vars in your main loop.
Of course I may be wrong cause this is the behaviour you want.
8! bits.. wow..
I just now read your post tjoink. I see that as a problem and also something else I discovered: when you press up, for instance, and then left, keeping up pressed, then release left, up will no longer be pressed. I tried putting the conditional if(upPressed)... in keyReleased, but that obviously only worked for one release. So I have another question about multiple keys in Java: How can I invoke a keyEvent myself? If I can't do this, then I think I have to do what tjoink said, testing for keyPresses in a main loop somewhere, continuously. So, how is the latter done? I was thinking I could keep the code as it is, but in my gameLoop I could test for up/down/right/left booleans. But this obviously can't be done straight like that or there would be an up/down/right/left action every 1/1000 of a second or less. So isn't there a static function Thread.wait(20), that I'm supposed to use, that will simulate the delay of a keyPressed call? What do coders commonly use? I found a few tutorials on multi-threading if I must do that. In which case I'd do the same as described above (with Thread.wait(20)), but this would all be happening in a different thread, hopefully pausing execution in *that* thread, and leaving other, continuously running threads to their business. Am I correct in my assumptions? Thanks for the great help. This isn't too important atm, but will be in a few days, so try to reply before 2005, thanks. ;P

edit: is it all right to just use java.util.Timer class to check for input every t milliseconds when I create the timer?

[Edited by - temp_ie_cant_thinkof_name on October 20, 2004 10:09:59 AM]
"I study differential and integral calculus in my spare time." -- Karl Marx

This topic is closed to new replies.

Advertisement