Search code examples
javakeylistenerarrow-keys

KeyListener not working the way I want it to for arrow keys?


I am making a the snake game and I have implemented the KeyListener class that listens to when the user presses the arrow keys or WASD keys.

In snake, when you press a movement key, the snake will continue to move if you just press a movement key once, and will only go in another direction once you enter a different movement command. However, in my program I have to hold the key down for the snake to move, I can't just press it once. How do I make it so that I just have to press the key once to move the snake?

Also, the WASD keys are working differently than the arrow keys. When I press a WASD key, the snake only moves one block and then stops, unlike the arrow keys where the snake moves as long as I hold down the arrow keys. How do I make the WASD keys work the same way as I want the arrow keys to work?

Here is the code:

public void keyTyped(KeyEvent e) {
}

public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A) {
        out.println("Left key pressed");
        // handle snake left movement
    } else if (e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D) {
        out.println("Right key pressed");
        // handle snake right movement
    } else if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W) {
        out.println("Up key pressed");
        // handle snake up movement
    } else if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_S) {
        out.println("Down key pressed");
        // handle snake down movement
    }
}

public void keyReleased(KeyEvent e) {
}

Solution

  • I have solved my problem, thank you @azurefrog, @Hovercraft Full Of Eels, and @AJNeufeld. Here is my solution in case other people have the same problem as mine. Disclaimer: I am not done with this game so the "snake" is just a block, I still have to figure out how to make it an actual snake. I am just posting this to show how I handled the movement of the snake.

    First, I made two global variables in my Snake class (the class of the game):

    private String currentDir = "";
    private Timer moveTimer = new Timer(100, new MoveListener());
    

    Then, I made a MoveListener class that extends the ActionListener class. This MoveListener class serves as the parameter for the moveTimer:

    private class MoveListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            out.println("timer action called");
            int snakeX = 0;
            int snakeY = 0;
            for (int row = 0; row < positions.length; row++) {
                for (int col = 0; col < positions[row].length; col++) {
                    if (positions[row][col] == 's') {
                        snakeX = row;
                        snakeY = col;
                    }
                }
            }
            if (currentDir.equals("left")) {
                positions[snakeX - 1][snakeY] = 's';
                positions[snakeX][snakeY] = '\u0000';
                repaint();
            } else if (currentDir.equals("right")) {
                positions[snakeX + 1][snakeY] = 's';
                positions[snakeX][snakeY] = '\u0000';
                repaint();
            } else if (currentDir.equals("up")) {
                positions[snakeX][snakeY - 1] = 's';
                positions[snakeX][snakeY] = '\u0000';
                repaint();
            } else if (currentDir.equals("down")) {
                positions[snakeX][snakeY + 1] = 's';
                positions[snakeX][snakeY] = '\u0000';
                repaint();
            }
        }
    }
    

    Finally, I made my KeyListener so that it simply set the variable currentDir based on the corresponding movement keys, and started the MoveTimer thread.

    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A) {
            out.println("Left key pressed");
            currentDir = "left";
            moveTimer.start();
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D) {
            out.println("Right key pressed");
            currentDir = "right";
            moveTimer.start();
        } else if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_W) {
            out.println("Up key pressed");
            currentDir = "up";
            moveTimer.start();
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_S) {
            out.println("Down key pressed");
            currentDir = "down";
            moveTimer.start();
        }
    }