0
\$\begingroup\$

I'm trying to make a turn-based game where my character is allow to move in any direction, but only by as much as the dice rolled allows him.

My problem is with how I'm using KeyListener: the character will keep moving while the button (let's say 'W' for up) is held down. It's almost impossible to move him by one increment per press.

How can I do the action just once even if the button is held down?

Here's my implementation:

package main;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyHandler implements KeyListener {

public boolean upPressed, downPressed, leftPressed, rightPressed;

@Override
public void keyTyped(KeyEvent e) {
}

@Override
public void keyPressed(KeyEvent e) {

    switch(e.getKeyCode()) {

        case KeyEvent.VK_W:
            upPressed = true;
            break;

    }

}

@Override
public void keyReleased(KeyEvent e) {

    switch(e.getKeyCode()) {

        case KeyEvent.VK_W:
            upPressed = false;
            break;

    }

}

And here's the KeyHandler logic:

package entity;

import main.GamePanel;
import main.KeyHandler;
import java.awt.*;
import java.util.concurrent.ThreadLocalRandom;


public class Player extends Entity {

GamePanel gp;
KeyHandler keyH;


public Player(GamePanel gp, KeyHandler keyH) {

    this.gp = gp;
    this.keyH = keyH;
    setDefaultValues();

}

public void setDefaultValues() {

    x = 100;
    y = 100;

}

public void update() {

    if (keyH.upPressed) {

        y -= 16;

    }

    else if (keyH.downPressed) {

        y += 16;

    }

    else if (keyH.leftPressed) {

        x -= 16;

    }

    else if (keyH.rightPressed) {

        x += 16;

    }


}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Why not have a bool in your KeyHandler logic that switches when the action is done and resets on release of the key? \$\endgroup\$
    – Zibelas
    Commented Mar 4 at 7:53

1 Answer 1

1
\$\begingroup\$

Here is the most common and likely easiest method:

// Store a boolean for the previous frames keydown value
private bool upPressedPrev;
private bool downPressedPrev;
...

public void update() {
    if (keyH.upPressed) {
        if (upPressedPrev == false) { y -= 16; upPressedPrev = true }
    }
    else { upPressedPrev = false; }
    // Repeat for all keys...
}

This works because after pressing down up (or any other key using this method), upPressedPrev would be false, so it would run the code once, then it sets upPressedPrev to true, meaning on the next frame, nothing would happen until the key is released. You could also implement a keyUp syntax using this method. Like this:

// Store a boolean for the previous frames keydown value
private bool upPressedPrev;
private bool downPressedPrev;
...

public void update() {
    if (keyH.upPressed) {
        if (upPressedPrev == false) { y -= 16; upPressedPrev = true }
    }
    else {
        if (upPressedPrev == true) { // Do something when the key is up; upPressedPrev = false; }
    }
    // Repeat for all keys...
}

This checks if the key isnt currently pressed, but was pressed the previous frame.

Hope this helps.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .