1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Development Java SE, handling simultaneous Keypresses.

Discussion in 'Software' started by WhiskeyAlpha, 5 Nov 2008.

  1. WhiskeyAlpha

    WhiskeyAlpha New Member

    Joined:
    5 May 2006
    Posts:
    838
    Likes Received:
    4
    Hi guys,

    I'm working on a network capable version of the old classic "Pong" for my final major project at Uni (using Netbeans 6.1) and I'm having a few problems already.

    Does anybody know of a way of handling simultaneous keyboard input in java? I'm currently using this simple piece of code in a KeyListener:
    Code:
    public void keyPressed(KeyEvent e){
         
                        if(e.getKeyCode() == e.VK_Q)
                             paddle.move(-10);
                        
                        if(e.getKeyCode() == e.VK_A)
                             paddle.move(10);
                        
                        if(e.getKeyCode() == e.VK_UP)
                             paddle2.move(-10);
                      
                        if(e.getKeyCode() == e.VK_DOWN)
                             paddle2.move(10);
                        
             
        }
        
        public void keyReleased(KeyEvent e){
           
                        if(e.getKeyCode() == e.VK_Q)
                             paddle.move(0);
                        
                        if(e.getKeyCode() == e.VK_A)
                             paddle.move(0);
                        
                        if(e.getKeyCode() == e.VK_UP)
                             paddle2.move(0);
                        
                        if(e.getKeyCode() == e.VK_DOWN)
                             paddle2.move(0);
                        
            
        } 
    This works reasonably well and I'm able to move both paddles. It does leave me with 2 major problems though:

    Firstly (and most importantly) this approach means that only one input can be handled at a time (i.e. both paddles can't be moved simultaneously).

    Secondly, there is a noticeable pause between pressing the key that moves a paddle and the actual paddle moving.

    Hopefully one of you guys might be able to help a student in distress :thumb:
     
  2. theevilelephant

    theevilelephant New Member

    Joined:
    5 Jan 2006
    Posts:
    1,334
    Likes Received:
    36
    I would say have a set of booleans ie: leftPressed, upPressed, downPressed, right Pressed. use your keyPressed method set a boolean to true (ie if left key was pressed set leftPressed to true), then in your keyReleased method do the opposite. Thats the only way I can think of doing it, i will have a play later and post any working code i get :)

    Edit: ok here is a little demo, pressing up and left or up and right at the same time will print out a string
    Code:
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import javax.swing.JFrame;
    
    
    
    public class Keys extends JFrame implements KeyListener{
    	boolean leftP=false;
    	boolean rightP=false;
    	boolean upP=false;
    	boolean downP=false;
    	
    	public static void main(String[] args){
    		Keys k = new Keys();
    	}
    	
    	Keys(){
    		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    		this.setVisible(true);
    		this.addKeyListener(this);
    		while(true){
    			if((leftP)&&(upP)){
    				System.out.println("Left and Up");
    				leftP=false; upP=false;
    			}
    			else if((rightP)&&(upP)){
    				System.out.println("Right and Up");
    				rightP=false; upP=false;
    			}
    		}
    	}
    	
    	
    	public void keyPressed(KeyEvent e) {
    	   if(e.getKeyCode() == e.VK_LEFT){
    		   leftP=true;
    	   }
           
           if(e.getKeyCode() == e.VK_RIGHT){
        	   rightP=true;
           }
           
           if(e.getKeyCode() == e.VK_UP){
        	   upP=true;
           }
         
           if(e.getKeyCode() == e.VK_DOWN){
        	   downP=true;
           }
    		
           if(e.getKeyCode() == e.VK_Q){
        	   System.exit(0);
           }
    	}
    
    	public void keyReleased(KeyEvent e) {
    		if(e.getKeyCode() == e.VK_LEFT){
    			   leftP=false;
    		   }
    	       
    	       if(e.getKeyCode() == e.VK_RIGHT){
    	    	   rightP=false;
    	       }
    	       
    	       if(e.getKeyCode() == e.VK_UP){
    	    	   upP=false;
    	       }
    	     
    	       if(e.getKeyCode() == e.VK_DOWN){
    	    	   downP=false;
    	       }
    		
    	}
    
    	public void keyTyped(KeyEvent arg0) {
    		// TODO Auto-generated method stub
    		
    	}
    
    }
    
     
    Last edited: 5 Nov 2008
  3. WhiskeyAlpha

    WhiskeyAlpha New Member

    Joined:
    5 May 2006
    Posts:
    838
    Likes Received:
    4
    Thanks theevilelephant :thumb:

    I've actually developed something very similar to what you suggest and have a different set of problems now :duh:

    Code:
    public void keyPressed(KeyEvent e){
         
                        if(e.getKeyCode() == e.VK_Q){
                            paddleUp = true;}
                        else if(e.getKeyCode() == e.VK_A){
                            paddleDown = true;}
                        else if(e.getKeyCode() == e.VK_UP){
                            paddle2Up = true;}
                        else if(e.getKeyCode() == e.VK_DOWN){
                            paddle2Down = true;}
                        
                        multipleKeyCheck();
                        singleKeyCheck();
                                                                            
        }
        
        public void singleKeyCheck(){
            if(paddleUp){
                paddle.move(-10);}
            else if(paddleDown){
                paddle.move(10);}
            else if(paddle2Up){
                paddle2.move(-10);}
            else if(paddle2Down){
                paddle2.move(10);}
        }
        
        public void multipleKeyCheck(){
            if(paddleUp && paddle2Up){
                paddle.move(-10);
                paddle2.move(-10);}
            else if(paddleUp && paddle2Down){
                paddle.move(-10);
                paddle2.move(10);}
            else if(paddleDown && paddle2Up){
                paddle.move(10);
                paddle2.move(-10);}
            else if(paddleDown && paddle2Down){
                paddle.move(10);
                paddle2.move(10);}
        }
        
        public void keyReleased(KeyEvent e){
          
                        if(e.getKeyCode() == e.VK_Q)
                            paddleUp = false;
                        if(e.getKeyCode() == e.VK_A)
                            paddleDown = false;
                        if(e.getKeyCode() == e.VK_UP)
                            paddle2Up = false;
                        if(e.getKeyCode() == e.VK_DOWN)
                            paddle2Down = false;
        } 
    New problems:

    1) when both paddles are moving simultaneously, the left paddle appears to move about twice as fast - semi-fixed - this is because the singleKeyCheck and multipleKeyCheck are both being processed and the left paddle gets moved first in singleKeyCheck, I believe.
    2) occasionally the right paddle won't move down - fixed
    3) various other weird behaviour - i.e. if both paddles are moving and then you lift off of one key, both paddles stop. once you reapply the key that you lifted off of, both panels move normally.
    4) the "delay" that is present at the first press (when holding the key) when using a keylistener for this job still troubles me. I wonder if there is a method to reduce it?

    probs just need to have a good look through my code and work out what's what
     
    Last edited: 5 Nov 2008
  4. theevilelephant

    theevilelephant New Member

    Joined:
    5 Jan 2006
    Posts:
    1,334
    Likes Received:
    36
    3) im guessing this is because you call the multipleKeyCheck in the key press method
    4) i have no idea, my dem doesnt seem to experience a delay

    Here is a slightly different version of my code. If you hold left and up "Left and Up" will be printed untill you let go, if you let go of either Left or Up then either "Left" or "up" will be printed untill you either let go or press another key. Im fairly sure this is what you are after? Compile it an have a play, see what you think
    Code:
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import javax.swing.JFrame;
    
    
    public class Keys extends JFrame implements KeyListener{
    	boolean leftP=false;
    	boolean rightP=false;
    	boolean upP=false;
    	boolean downP=false;
    	
    	public static void main(String[] args){
    		Keys k = new Keys();
    	}
    	
    	Keys(){
    		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    		this.setVisible(true);
    		this.addKeyListener(this);
    		while(true){
    			if((leftP)&&(upP)){
    				System.out.println("Left and Up");
    				//leftP=false; upP=false;
    			}
    			else if((rightP)&&(upP)){
    				System.out.println("Right and Up");
    				//rightP=false; upP=false;
    			}
    			else if(leftP){
    				System.out.println("left");
    			}
    			else if(upP){
    				System.out.println("Up");
    			}
    		}
    	}
    	
    	public void keyPressed(KeyEvent e) {
    	   if(e.getKeyCode() == e.VK_LEFT){
    		   leftP=true;
    	   }
           
           if(e.getKeyCode() == e.VK_RIGHT){
        	   rightP=true;
           }
           
           if(e.getKeyCode() == e.VK_UP){
        	   upP=true;
           }
         
           if(e.getKeyCode() == e.VK_DOWN){
        	   downP=true;
           }
    		
           if(e.getKeyCode() == e.VK_Q){
        	   System.exit(0);
           }
    	}
    
    	public void keyReleased(KeyEvent e) {
    		if(e.getKeyCode() == e.VK_LEFT){
    			   leftP=false;
    		   }
    	       
    	       if(e.getKeyCode() == e.VK_RIGHT){
    	    	   rightP=false;
    	       }
    	       
    	       if(e.getKeyCode() == e.VK_UP){
    	    	   upP=false;
    	       }
    	     
    	       if(e.getKeyCode() == e.VK_DOWN){
    	    	   downP=false;
    	       }
    		
    	}
    
    	public void keyTyped(KeyEvent arg0) {}
    
    }
    
     
  5. dfhaii

    dfhaii internets

    Joined:
    24 Mar 2002
    Posts:
    520
    Likes Received:
    0
    Code:
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import javax.swing.JFrame;
    
    
    public class Keys extends JFrame {
      volatile boolean mLeftPressed;
      volatile boolean mRightPressed;
      volatile boolean mUpPressed;
      volatile boolean mDownPressed;
    	
    	public static void main(String[] args){
    		Keys k = new Keys();
    	}
    	
      public Keys(){
        super("KeyTest");
    		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    		this.setVisible(true);
    		this.addKeyListener(new KeyAdapter(){
          @Override
          public void keyPressed(KeyEvent e) {
            switch(e.getKeyCode()){
              case KeyEvent.VK_LEFT:
                mLeftPressed = true;
                break;
              case KeyEvent.VK_RIGHT:
                mRightPressed = true;
                break;
              case KeyEvent.VK_UP:
                mUpPressed = true;
                break;
              case KeyEvent.VK_DOWN:
                mDownPressed = true;
                break;
              case KeyEvent.VK_Q:
                System.exit(0);
                  break;
            }
          }
          
          @Override  
          public void keyReleased(KeyEvent e) {
            switch(e.getKeyCode()){
              case KeyEvent.VK_LEFT:
                mLeftPressed = false;
                break;
              case KeyEvent.VK_RIGHT:
                mRightPressed = false;
                break;
              case KeyEvent.VK_UP:
                mUpPressed = false;
                break;
              case KeyEvent.VK_DOWN:
                mDownPressed = false;
                break;
              case KeyEvent.VK_Q:
                System.exit(0);
                  break;
            }
          }
        });
        
        Thread KeyPressedMonitor = new Thread(){
          public void run(){
            while(true){
              //check for your buttons being pressed here
              if(mLeftPressed)
                System.out.println("LEFT");
              if(mRightPressed)
                System.out.println("RIGHT");
              if(mUpPressed)
                System.out.println("UP");
              if(mDownPressed)
                System.out.println("DOWN");
              try{
                Thread.sleep(1);
              }catch(InterruptedException e){}
            }
          }
        };
        KeyPressedMonitor.start();
      }
    }
    
    Something like that might work for you? I suspect you're probably having problems with your gui due to not ensuring updates to swing components are happening on the EDT, and by using the EDT to do heavy work killing it momentarily.

    I've not tried even building that code, but I'm fairly sure it will and it'll supply you with a set of bools so you know which buttons are down at any one time.
     
    Last edited: 27 Nov 2008
  6. JazzXP

    JazzXP Eh! Steve

    Joined:
    30 Apr 2002
    Posts:
    1,669
    Likes Received:
    13
    You beat me to it dfhaii, I was going to suggest using a thread to monitor the booleans as well.
     

Share This Page