1

I'm making a 2D game using Java and I have a key listener to handle player movements and other stuff. It works completely fine most of the time. However, sometimes it glitches. For example, I'll be holding the "A" key to make the character go to the left and, when I release it, the character keeps moving like if I was still holding the key. I assume that's because the key listener is for some reason not detecting the keyReleased event.

I've been trying to figure out why for a while now but still got no idea why it does that.

Here is part of my code if you want to take a look at it.

Key Listener class

package input;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import game.Game;

public class KeyboardInput extends KeyAdapter {
   public KeyboardInput() {
   }

   // Detects pressed keys
   public void keyPressed(KeyEvent e) {
      if (Game.init) {
         Keys.Keys[e.getKeyCode()] = true;
      }
   }

   // Detects released keys
   public void keyReleased(KeyEvent e) {
      if (Game.init) {
         Keys.Keys[e.getKeyCode()] = false;
      }
   } 
}

Part of my display class

 // Display Constructor
public Display(String title, String gameVersion, int width, int height) {
  this.title = title;
  this.width = width;
  this.height = height;
  this.gameVersion = gameVersion;

  createDisplay();
}

// Creates display
private void createDisplay() {
  frame = new JFrame(title + " v. " + gameVersion);
  frame.setSize(width, height);
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setResizable(false);
  frame.setLocationRelativeTo(null);
  frame.setVisible(true);
  frame.setFocusable(true);

  canvas = new Canvas();
  canvas.setPreferredSize(new Dimension(width, height));
  canvas.setMinimumSize(new Dimension(width, height));
  canvas.setMaximumSize(new Dimension(width, height));
  canvas.setBackground(Color.WHITE);

  frame.add(canvas);
  frame.addKeyListener(new KeyboardInput()); // ADDING KEY LISTENER TO THE JFRAME
  canvas.addMouseListener(new MouseInput());
  frame.pack();
  if (frame.getKeyListeners().length > 0) {
    System.out.println("Key listener initialized");
  } else {
    System.out.println("ERROR : Key listener couldn't initialize");
  }
  if (canvas.getMouseListeners().length > 0) {
    System.out.println("Mouse listener initialized");
  } else {
    System.out.println("ERROR : Mouse listener couldn't initialize");
  }
}

// Updates display (called every frame)
public void update() {
  frame.requestFocus();
  tick++;
  lasttime = currtime;
  currtime = System.nanoTime();
  delta = (currtime - lasttime) / 1000000000;
  fps = (float) (1 / delta);
  if ((tick / fps) >= SAVE_TIME) {
    tick = 0;
    saveNextTick = true;
    System.out.println("FPS = " + Math.round(getFPS()));
    try {
      System.out.println("MOUSE POSITION = (" + frame.getMousePosition().getX() + ", "
        + frame.getMousePosition().getY() + ")");
    } catch (Exception e) {
      System.out.println("Mouse out of screen. Could not get mouse position (NullPointerException)");
    }
  }

  if (saveNextTick) {
    Save.saveGame("Save");
    saveNextTick = false;
  }
}

Method that handles player movement

private void checkMove() {
   int speed = moveSpeed;
   int x1 = getxPos();
   int x2 = x1 + getTexture().getImage().getWidth();
   int y1 = getyPos();
   int y2 = y1 + getTexture().getImage().getHeight();
   if ((Keys.Keys[KeyEvent.VK_W] || Keys.Keys[KeyEvent.VK_S]) &&       (Keys.Keys[KeyEvent.VK_A] || Keys.Keys[KeyEvent.VK_D])) {
      speed = diagonalMoveSpeed;
   }
   int d = Math.max((int) (speed / Display.getFPS()), 1);
   if (speed / Display.getFPS() < 1 && Util.randInt(0, 100) > speed /  Display.getFPS() * 100) {
      d = 0;
   }
   if (Keys.Keys[KeyEvent.VK_W] && !States.currentState.checkCollision(x1,  x2, y1 - d, y2 - d)) {
      move(0, -d);
   }
   if (Keys.Keys[KeyEvent.VK_A] && !States.currentState.checkCollision(x1 - d, x2 - d, y1, y2)) {
      move(-d, 0);
   }
   if (Keys.Keys[KeyEvent.VK_S] && !States.currentState.checkCollision(x1, x2, y1 + d, y2 + d)) {
      move(0, d);
   }
   if (Keys.Keys[KeyEvent.VK_D] && !States.currentState.checkCollision(x1 + d, x2 + d, y1, y2)) {
      move(d, 0);
   }
}

Thanks in advance for helping. If you need to see any other part of the code to figure out the problem, just ask.

P.S. : I know this is probably not the simplest way to write a key listener / get keyboard input, but it's the only way I know. I am currently searching to find a better way and I'll change it once I do.

Olithegoalie
  • 86
  • 10
  • Could u post your key class? or the class that handles movement based on key input – DarkV1 Jul 05 '16 at 23:13
  • Sure! I've edited my original post. Also, I changed the key listener class a bit. I didn't expect it to fix the problem but it's just a simpler way of doing it. Also, I thought that maybe the problem is that my keyboard is garbage and the keys keep getting stuck. I remembered that sometimes I've had this issue in other games. I'll try to test it on another computer see if that'll fix the problem. – Olithegoalie Jul 06 '16 at 04:41
  • Check if the keyevent is still firing by putting a print statement when u let go of the key. That will tell u if theres something wrong with either ur keyclass(which i doubt) or ur keyboard. – DarkV1 Jul 06 '16 at 17:56
  • Ok thanks I'll try it. – Olithegoalie Jul 06 '16 at 20:16

1 Answers1

0

you should do something like keyboard debouncing. Because when we press a keyboard button on long time. Because when we try to write a text in editor by long press keyboard key, it would generated more character after we released the key.

Read the corresponding QA:
implementing debounce in Java

Community
  • 1
  • 1
ישו אוהב אותך
  • 28,609
  • 11
  • 78
  • 96