Jollyfreak
Jollyfreak

Reputation: 37

Handling two keypresses in java

I have a problem in my code, because i don't know how to make picture move diagonal when you press ARROW UP and ARROW LEFT at the same time, etc.. Here is my code:

 public void keyPressed(KeyEvent ke) {
    switch (ke.getKeyCode()) {
    case KeyEvent.VK_RIGHT: {
        cordX += 5;
    }
        break;
    case KeyEvent.VK_LEFT: {
        cordX -= 5;
    }
        break;
    case KeyEvent.VK_DOWN: {
        cordY += 5;
    }
        break;
    case KeyEvent.VK_UP: {
        cordY -= 3;
    }
        break;
    }
    repaint();
}

I don't know if this would work

case KeyEvent.VK_UP  &&  KeyEvent.VK_LEFT: {
        cordY += 5;
    }
        break;

Upvotes: 0

Views: 74

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347244

If you are using Swing components, use the Key Bindings API, see How to Use Key Bindings, it will solve a rafter of issues...

In any case, the solution is (basically) the same, what you need to do is define a series of flags which define which keys are currently pressed and at a regular interval update the state of the variables affected by those flags

private boolean down, up, left, right;
//...

public void keyPressed(KeyEvent ke) {
    switch (ke.getKeyCode()) {
        case KeyEvent.VK_RIGHT:
            right = true;
            break;
        case KeyEvent.VK_LEFT:
            left = true;
            break;
        case KeyEvent.VK_DOWN:
            down = true;
            break;
        case KeyEvent.VK_UP:
            up = true;
            break;
    }
    updateState();
}

public void keyReleased(KeyEvent ke) {
    switch (ke.getKeyCode()) {
        case KeyEvent.VK_RIGHT:
            right = false;
            break;
        case KeyEvent.VK_LEFT:
            left = false;
            break;
        case KeyEvent.VK_DOWN:
            down = false;
            break;
        case KeyEvent.VK_UP:
            up = false;
            break;
    }
    updateState();
}

protected void updateState() {
    if (right) {
        cordX += 5;
    } else if (left) {
        cordX -= 5;
    }
    if (down) {
        cordY += 5;
    } else if (up) {
        cordY -= 3;
    }
    repaint();
}

You could then use a javax.swing.Timer to schedule a regular call back, which could be used to call updateState (instead of calling it from the key event handlers).

Have a look at How to use Swing Timers for more details...

Upvotes: 4

J4v4
J4v4

Reputation: 810

You can use a Timer.

public class MyClass extends KeyAdapter implements ActionListener {

    private Timer timer; //this timer will update your object's position
    private int vx = 0; //these values indicate your objects velocity
    private int vy = 0; //they are updated as your arrow keys are pressed

    public MyClass() {
        this.timer = new Timer(100 /*the delay*/, this/*the listener*/);
        //the delay indicated how frequently you want to update your position, i chose 100ms, you may chose a different number
    }

    @Override public void keyPressed(KeyEvent ke) {
        switch (ke.getKeyCode()) {
            case KeyEvent.VK_RIGHT:
                vx = 5;
            break;
            case KeyEvent.VK_LEFT:
                vx = -5;
            break;
            case KeyEvent.VK_DOWN:
                vy = 5;
            break;
            case KeyEvent.VK_UP:
                vy = -3;
            break;
        }
        this.timer.start(); //start your timer when a key is pressed (will do nothing if it's already running)
    }

    //obviously, you will need to stop your objects once the keys are released.
    @Override public void keyReleased(KeyEvent ke) {
        switch(ke.getKeyCode()) {
            case KeyEvent.VK_RIGHT:
                vx = 0;
            break;
            case KeyEvent.VK_LEFT:
                vx = 0;
            break;
            case KeyEvent.VK_DOWN:
                vy = 0;
            break;
            case KeyEvent.VK_UP:
                vy = 0;
            break;
        }
        if(vx == 0 && vy == 0) this.timer.stop(); //no need to run the timer if no key is down
    }

    //this will be called regularly by the timer
    @Override public void actionPerformed(ActionEvent ae) {
        cordX += vx; //you just update the positions
        cordY += vy; //according to your variables
        repaint(); //then repaint
    }
}

Edit: You can optimize this to avoid weird behaviour when (for example) both left and right key are pressed.

Upvotes: 0

Related Questions