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.