1
\$\begingroup\$

I'm making a game Applet with Java that uses KeyListeners to control a paddle (for a game like Breakout/Pong). My basic implementation goes like this:

public void keyPressed(KeyEvent e) {
    switch (e.getKeyCode()) {
        case KeyEvent.VK_LEFT:
            direction = "LEFT";
            break;
        case KeyEvent.VK_RIGHT:
            //repeat for the rest
    }
}
public void keyReleased(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_RIGHT)
        direciton = "";//paddle doesn't move
}

My problem is that when the user tries to change the direction of the paddle twice too fast (let's say you press left, then right and left again super fast), the paddle freezes for a split second, and continues to move along its direction.

I understand that the problem is the logic in my code, but I can't think of a better implementation. What am I missing?

\$\endgroup\$
1
\$\begingroup\$

It needs state.

At the moment, this is what happens if you press Left, press Right, then release Left:

-> keyPressed(left):  direction = "LEFT";
-> keyPressed(right): direction = "RIGHT";
-> keyReleased(left): direction = "";

The paddle doesn't move, even though Right is still pressed!

You can solve this by checking in keyReleased if the opposite direction is still down and reset the direction to "" only if it isn't.

Unfortunately, since KeyListeners only tell you when keys go down and up, not whether they are down at the moment. You must track this state yourself. You can do it by setting variables leftIsDown and rightIsDown in the keyPressed and keyReleased cases for each key.

\$\endgroup\$
0
\$\begingroup\$

... A more expensive way:

public class TimerExample implements KeyListener {
private Timer right;
private Timer left;
private Timer down;
private Timer up;
public void defineTimers() {
    ActionListener l = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // Move LEFT
        }
    };
    right = new Timer(10, l);
    ActionListener r = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // Move RIGHT
        }
    };
    right = new Timer(10, r);
    ActionListener d = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // Mode DOWN
        }
    };
    down = new Timer(10, d);
    ActionListener u = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // Move UP
        }
    };
    up = new Timer(10, u);
}

    @Override
public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub

}
@Override
public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_UP) {
        up.start();
    } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
        down.start();
    } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
        right.start();
    } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
        left.start();
    }
}
@Override
public void keyReleased(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_UP) {
        up.stop();
    } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
        down.stop();
    } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
        right.stop();
    } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
        left.stop();
    }
}

}

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to gamedev.se! Could you add some explanation of what the code is doing and why it solves the issue at hand? Poorly documented blocks of code are not as helpful as well explained ones. \$\endgroup\$ – Vaillancourt Mar 28 '18 at 11:59
0
\$\begingroup\$

States can be achieved with enums, I'm writing a similar game too and thanks to @Anko I implemented his solution like this:

public enum PaddleWay {
    UP, DOWN, STOP
}

private void handleMovement(){
    if(p1paddleway == PaddleWay.STOP) {
        paddle1yPos = paddle1yPos;
    }
    if(p1paddleway == PaddleWay.UP) {
        paddle1yPos -= PADDLESPEED;
    }
    if(p1paddleway == PaddleWay.DOWN) {
        paddle1yPos += PADDLESPEED;
    }
    if(p2paddleway == PaddleWay.STOP) {
        paddle2yPos = paddle2yPos;
    }
    if(p2paddleway == PaddleWay.UP) {
        paddle2yPos -= PADDLESPEED;
    }
    if(p2paddleway == PaddleWay.DOWN) {
        paddle2yPos += PADDLESPEED;
    }
}

    @Override
public void keyPressed(KeyEvent e) {
    switch(e.getKeyCode()) {
    //p1 inputs
    case KeyEvent.VK_A:
        p1paddleway = PaddleWay.UP;
        break;
    case KeyEvent.VK_Z:
        p1paddleway = PaddleWay.DOWN;
        break;
    //p2 inputs
    case KeyEvent.VK_O:
        p2paddleway = PaddleWay.UP;
        break;
    case KeyEvent.VK_K:
        p2paddleway = PaddleWay.DOWN;
        break;
    }
}
@Override
public void keyReleased(KeyEvent e) {
    switch(e.getKeyCode()) {
    //p1 inputs
        case KeyEvent.VK_A:
            p1paddleway = PaddleWay.STOP;
            break;
        case KeyEvent.VK_Z:
            p1paddleway = PaddleWay.STOP;
            break;
    //p2 inputs
        case KeyEvent.VK_O:
            p2paddleway = PaddleWay.STOP;
            break;
        case KeyEvent.VK_K:
            p2paddleway = PaddleWay.STOP;
            break;
    }

It's a little long but you can just copy paste once you write one method and simply manipulate.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.