0

In my code, when detecting an arrow key the character will move accordingly. This is done through a Timer and TimerTask to schedule "movements" of the character. However, when another key is pressed it causes the character to flip around and malfunction completely. I am looking for a way to stop the user from pressing any keys on the keyboard, until the character is finished moving.

My code is as follows:

@FXML
public void moveCharacter(KeyEvent event) {
        switch (event.getCode()){
            case D, RIGHT:
                try {
                    moveForward();
                } catch (URISyntaxException | InterruptedException e) {
                    throw new RuntimeException(e);
                }
                break;
            case A, LEFT:
                try {
                    moveBack();
                } catch (URISyntaxException e) {
                    throw new RuntimeException(e);
                }
                break;
         }
}

Initially, I thought to use a timer to prevent keyboard input after a set amount of time. This was done like so:

final long THRESHOLD = 1_500_000_000L;

private long lastMoveNanos;

long now = System.nanoTime();

if (lastMoveNanos <= 0L || now - lastMoveNanos >= THRESHOLD) {
       //switch case here
}
lastMoveNanos = now;

However, it didn't work and my character still malfunctioned. I had also used Thread.sleep within the switch case, but it just stopped my character from moving and teleported it to the destination.

Thank you in advance for any sort of advice.

  • 2
    I wouldn't try to disable the keyboard. Instead, try something that ignores the keyboard while the character is being moved. Maybe `private AtomicBoolean moveInProgress = new AtomicBoolean (false);` instance variable. Then `moveCharacter (KeyEvent event) { if ( ! moveInProgress.compareAndSet (false, true)) { return; } switch (event.getCode()) { ... }` Then, after the `switch` block, have `moveInProgress.set (false);` as the last line in that method. – Old Dog Programmer Aug 19 '23 at 18:49
  • 4
    As an aside, I would avoid using `Timer` / `TimerTask` for this. Introducing a background thread to handle what appears to be inherently UI-centric makes everything more complicated. Just use something from the `javafx.animation` package. And if you need a task to execute on the _JavaFX Application Thread_ periodically, see https://stackoverflow.com/a/60685975/6395627. Note if you keep everything on the FX thread then you can use a simple `boolean` instead of an `AtomicBoolean` as suggested by Old Dog Programmer. – Slaw Aug 19 '23 at 21:25
  • Slaw, I'm not able to use the javafx.animation package because I am using ImageView as the character, and having the Timer/TimerTask to change the Image of the character as it moves. – Zhe Hin Yap Aug 20 '23 at 09:28
  • @OldDogProgrammer, the advice u gave unfortunately didn't work, however it did help in fixing the problem as I managed to use a boolean variable and an if-else statement to solve the problem – Zhe Hin Yap Aug 20 '23 at 10:32
  • Interesting. I wonder why `AtomicBoolean` didn't work, but a primitive `boolean` did work? Did I make a mistake with `.compareAndSet` ? Anyway, Slaw pointed out the primitive should work, which it did. – Old Dog Programmer Aug 20 '23 at 16:35

1 Answers1

0
  1. define a atomic boolean attribute for your controller
private AtomicBoolean isPressed = new AtomicBoolean(false);
  1. then you can check on any key press if a key is pressed already and set the isPressed to false whenever the key action is completed:
    @FXML
    public void moveCharacter(KeyEvent event) {
        if(isPressed.get()) return;
        
        isPressed.set(true);
        switch (event.getCode()){
            case D, RIGHT:
                try {
                    moveForward();
                    
                } catch (URISyntaxException | InterruptedException e) {
                    throw new RuntimeException(e);
                }
                break;
            case A, LEFT:
                try {
                    moveBack();
                } catch (URISyntaxException e) {
                    throw new RuntimeException(e);
                }
                break;
        }
        isPressed.set(false);
    }
nao
  • 1