Keyboard Input Repeat Lags

Started by MattholomewCup, September 29, 2013, 03:50:19

Previous topic - Next topic

MattholomewCup

Hey all,

I'm still getting the hang of LWJGL and I am hitting a minor snag. I'm just trying to get a block to move smoothly around the screen and I'm having an issue with the Keyboard inputs. I use the
Keyboard.enableRepeatEvents(true);
code so that I can hold down WASD to move the object on the screen. It does do that; however, there's a half-second or so lag between when I press down the key and when the object begins to move. Could this simply have to do with my OS's key repeat rate preventing the code from recognizing that I'm actually holding down the key?

EDIT: Maybe I can be more precise, when I press the key, the box will move one increment, wait for a half-second, and then move rapidly. The lag is only on the repeat, not any movement.

Here's my input code, if that helps out. It's almost verbatim from the tutorial on the LWJGL site wiki:
public void pollInput(Components character){
		if(Mouse.isButtonDown(0)){ //left click
			int mouseX = Mouse.getX();
			int mouseY = Mouse.getY();
			System.out.println("Mouse clicked at " + mouseX + ", " + mouseY);
		}
		while(Keyboard.next()){
			if(Keyboard.getEventKeyState()){
				if(Keyboard.getEventKey() == Keyboard.KEY_W){
					System.out.println("Move Forward");
					character.y += 4;
				}
				if(Keyboard.getEventKey() == Keyboard.KEY_A){
					System.out.println("Move Left");
					character.x -=4;
				}
				if(Keyboard.getEventKey() == Keyboard.KEY_D){
					System.out.println("Move Right");
					character.x += 4;
				}
				if(Keyboard.getEventKey() == Keyboard.KEY_S){
					System.out.println("Move Back");
					character.y -= 4;
				}
			} else {
				if(Keyboard.getEventKey() == Keyboard.KEY_W){
					System.out.println("Stop Moving Forward");
				}
				if(Keyboard.getEventKey() == Keyboard.KEY_A){
					System.out.println("Stop Moving Left");
				}
				if(Keyboard.getEventKey() == Keyboard.KEY_D){
					System.out.println("Stop Moving Right");
				}
				if(Keyboard.getEventKey() == Keyboard.KEY_S){
					System.out.println("Stop Moving Back");
				}
			}
		}
	}

Fool Running

Quote from: MattholomewCup on September 29, 2013, 03:50:19
Could this simply have to do with my OS's key repeat rate preventing the code from recognizing that I'm actually holding down the key?
Basically, yes. For games, you want to do something more like:
if (Keyboard.isKeyDown(Keyboard.KEY_W){
    character.y += 0.4
}

This is where limiting your framerate to 60fps with Display.sync() comes in handy (so you know how fast it will be moving). Otherwise, you can use the timer to figure out how much time has passed since the last frame and move a distance based on that amount (this doesn't depend on framerate).
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

MattholomewCup

Hey! Getting rid of the
while(Keyboard.next())
wrapper and using the series of if statements got it. Thanks for the tip! It looks a bit uglier but it does work as intended. Is this generally the best way to get games working? Is there a way to work around the computer's key repeat limitations beyond this? I am using Display.sync() already so that seems all set.

Thanks!

RiverC

Like he said, smooth motion should be done by checking 'isKeyDown' every frame. You use the delta (which there are ways to calculate somewhat more smoothly) to figure out how much to multiply your movement rate by.

The delta at ~60fps is ~17ms

So to move 4 units a second, you'd do this calculation: (4*.001*delta) or to fudge it just (4*.001*17).

Dropping the 'while(Keyboard.next()' will mean if you have a lot of keys you are polling, the game will still be doing extra operations it could avoid doing if no keys are being pressed.

MattholomewCup

Oooh! I was misunderstanding how this worked out, that makes a lot of sense now.

I was doing it by performing the movement operation every time it polls the input, but it seems like you're suggesting that it should be done by performing the movement action on every loop until it detects that the key has been removed, is that about right? This seems like a much more sane way of thinking about it.