yet another keyboard input problem

Hi there!

I just programmed my first game in java, a space-invaders like game where you control a spaceship and fire at some astroide-whatevers.

I designed the keyboard input in the following manner, and everything works fine. The problem appears when I hold down the right- and the down-arrow keys and want to fire(press space) simultaneously: the fire-method is not called, allthough this works with all other combinations of arrow keys.

class MyKeyListener extends KeyAdapter {

    public void keyPressed(KeyEvent ke) {
    	
    	switch(ke.getKeyCode()) { 
    	case KeyEvent.VK_RIGHT:  
        	control.setRight(true); 
        	control.setLeft(false); break;
        case KeyEvent.VK_LEFT:   
        	control.setLeft(true); 
        	control.setRight(false); break;
        case KeyEvent.VK_UP:   
        	control.setUp(true);
        	control.setDown(false); break;    	
        case KeyEvent.VK_DOWN:  
        	control.setDown(true); 
        	control.setUp(false); break; 
        case KeyEvent.VK_SPACE:
        	control.setFire(true);
        	fire();
        	break;   
        	}
    	}
    }
    
    public void keyReleased(KeyEvent ke) {
    	switch(ke.getKeyCode()) {
        case KeyEvent.VK_LEFT:  
        	control.setLeft(false); break;     	
        case KeyEvent.VK_RIGHT:  
        	control.setRight(false); break;  
        case KeyEvent.VK_UP:   
        	control.setUp(false); break;    	
        case KeyEvent.VK_DOWN:  
        	control.setDown(false); break;
        case KeyEvent.VK_SPACE:
        	control.setFire(false); break;
    	}
    }
}

}

I tried calling the fire()-method where I am working with the control.booleans for the movement of the ship, but hitting the spacebar with these two keys down seems to have no effect at all.

So my question is if anyone knows why it’s like that. Just a solution to the problem would also be satisfying to me :wink:

I see no breaks at the end of your case statements.

Java is like C, case statements “fall through” if there is no break.

I see the breaks ::slight_smile:
But thx for the first reply!

Don’t use a switch/case statement. Switch/cases stop as soon as the first key is found. If there’s a second key that needs to be handled, it will never have a chance to be interpreted. Instead, use a series of “if” statements so that every key is handled. e.g.:


setLeft(false);
setRight(false);
setDown(false);
setUp(false);

if(keyCode == KeyEvent.VK_LEFT) setLeft(true);
if(keyCode == KeyEvent.VK_RIGHT) setRight(true);
if(keyCode == KeyEvent.VK_DOWN) setDown(true);
if(keyCode == KeyEvent.VK_UP) setUp(true);

The exact implementation is up to you, but I think you get the idea. :slight_smile:

Ah yes, now I do.

Formatting lesson. break is a statement. Put it on its own line.

Doesn’t work with ifs neither, just tried it this way…

My initial idea was right, everytime you press a key the event is fired and the method keyPressed() is called. So it should work with switch.

Still don’t have a clue why it works for left+down, left+up, right+up. Only right+down doesn’t work…

I start wondering if my Keyboard is f***ed, which I can’t check right now. I’ll try this tomorrow…

Concerning the breaks: they’re kind of self-evident to me so I don’t want to waste any space for them, but maybe your right to have better readability.

I read somewhere that it’s possible to change the system status of keys being pressed. Then they appear like released/not pressed, allthough they are actually held down. Does anyone know how to do this?

Its possible you are running into keyboard scanning issues.

Id suggest firing up the JInput test prog, which is about as low level as you can get, and see if it shows both keys down at the same time.

I start wondering if my Keyboard is f***ed, which I can’t check right now. I’ll try this tomorrow…

Concerning the breaks: they’re kind of self-evident to me so I don’t want to waste any space for them, but maybe your right to have better readability.

right+down works, as does e.g. right+up+space, but right+down+space doesn’t.

But never the less - that’s a good idea, where do I get this JInput test prog, or how can I start it if it’s shipped with the developer kit?

[quote=“steve99,post:6,topic:26263”]
Can you post the part of the main loop that acts upon the keys being down?

I’m sorry my post was confusing. What I was trying to say is that you’d normally record when keys are up or down, then set the values in the main loop. Here’s a bit of real world code I’ve used:


    private static final boolean[] keys = new boolean[256];

    public void main()
    {
        ...

        while(true)
        {
                if(keys[KeyEvent.VK_LEFT]) angle++;
                if(keys[KeyEvent.VK_RIGHT]) angle--;
                if(angle >= 360) angle -= 360;
                if(angle < 0) angle += 360;
    
                stepx = Math.cos(Math.toRadians(angle+90));
                stepy = Math.sin(Math.toRadians(angle+90));
                
                if(keys[KeyEvent.VK_UP])
                {
                    x += stepx * 6.0; 
                    y += stepy * 6.0;
                }
    
                if(keys[KeyEvent.VK_DOWN])
                {
                    x -= stepx * 6.0;
                    y -= stepy * 6.0;
                }

                ....
        }
    }

    public void keyPressed(KeyEvent e)
    {
        keys[e.getKeyCode()] = true;
    }

    public void keyReleased(KeyEvent e)
    {
        keys[e.getKeyCode()] = false;
    }

    public void keyTyped(KeyEvent e) {}

Can you post the part of your code that’s the equivalent of the main loop processing above? I’m guessing the problem is there.

This is what I do directly in the switch statement for VK_SPACE in keyPressed (I don’t have a fire()-method(see above)):


control.setFire(true)
bullet = new Bullet(ship.getXPos() + ship.getWidth()/2 - bullet.getWidth()/2 , ship.getYPos());
bulletList.add(bullet); 

bulletList is an ArrayList.

The control class looks like this:


class Control {
	// stores pressed keys
	
	private boolean up=false, down=false, right=false, left=false;
	private boolean fire=false, pause=false;
	
	public synchronized void setUp(boolean b) {up = b;}
	public synchronized void setDown(boolean b) {down = b;}
	public synchronized void setRight(boolean b) {right = b;}
	public synchronized void setLeft(boolean b) {left = b;}
	public synchronized void setFire(boolean b) {fire = b;}
	public synchronized void setPause(boolean b) {pause = b;}
	
	public synchronized boolean isUp() {return up;}
	public synchronized boolean isDown() {return down;}
	public synchronized boolean isRight() {return right;}
	public synchronized boolean isLeft() {return left;}
	public synchronized boolean isFire() {return fire;}
	public synchronized boolean isPause() {return pause;}
	
}

I don’t do anything concernig the spacebar anywhere, the only appearances of the control class in the main loop (and anywhere else) are these:


                                if (io.control.isRight()) 
					io.ship.setXSpeed(io.ship.getSPEED());
				else if (io.control.isLeft())
					io.ship.setXSpeed(-io.ship.getSPEED());
				else
					io.ship.setXSpeed(0);
				
				if (io.control.isDown()) 
					io.ship.setYSpeed(io.ship.getSPEED());
				else if (io.control.isUp())
					io.ship.setYSpeed(-io.ship.getSPEED());
				else
					io.ship.setYSpeed(0);

If I am not totally mistaken, that’s exactly what you do…

I just checked my keyboard with this: http://www.passmark.com/products/keytest.htm

The program doesn’t get down+right+space either. I’ll need to try other keyboards… >:(

I found some combinations which allow u to press 7 keys at once, if you stick to a specific order pressing them. Other combinations allow only 2 keys at once. This is so annoying.

So I have to find a fire key that allows me to press two arrow keys (in any combination) simultaneously…
Can I then be sure that this works with all keyboards?

Thank you for your efforts so far!
Sorry for bothering you, but maybe there’s a workaround? hardly having any hope

I was afraid that would be the case. I’ve been pouring through the code you posted. Other than being a bit unorthidox (i.e. a bit wordy on the number of lines) nothing stood out as wrong.

[quote]Thank you for your efforts so far!
Sorry for bothering you, but maybe there’s a workaround? hardly having any hope
[/quote]
You’ll need to learn the status of each key when pressed/not pressed in order to develop a workaround. Try something like this:

    private static final boolean[] keys = new boolean[256];

    public void keyPressed(KeyEvent e)
    {
        keys[e.getKeyCode()] = true;

        System.out.println("Pressed: "+e.getKeyCode());

        System.out.println(keys[KeyEvent.VK_LEFT]+":"+keys[KeyEvent.VK_RIGHT]+":"+keys[KeyEvent.VK_UP]+":"+keys[KeyEvent.VK_DOWN]+":"+keys[KeyEvent.VK_SPACEBAR]);
    }

    public void keyReleased(KeyEvent e)
    {
        keys[e.getKeyCode()] = false;

        System.out.println("Released: "+e.getKeyCode());
        System.out.println(keys[KeyEvent.VK_LEFT]+":"+keys[KeyEvent.VK_RIGHT]+":"+keys[KeyEvent.VK_UP]+":"+keys[KeyEvent.VK_DOWN]+":"+keys[KeyEvent.VK_SPACEBAR]);
    }

    public void keyTyped(KeyEvent e) {}

That should allow you to check the status of the keys at all times, and perhaps see if you are/are not seeing keypresses. Feel free to improve upon the program as required. However, the most likely thing you’ll find is that your keyboard cuts a few corners on cost and simply doesn’t allow for certain key combos. :frowning:


setLeft(keyCode == KeyEvent.VK_LEFT);
setRight(keyCode == KeyEvent.VK_RIGHT);
setDown(keyCode == KeyEvent.VK_DOWN);
setUp(keyCode == KeyEvent.VK_UP);

:stuck_out_tongue: