moving in a 3d space: movement delay when pressing keys

Started by
2 comments, last by Katie 13 years ago
Hi, sorry if this has been answered somewhere, I checked google and searched the forums here and found nothing. If it has already been answered I would appreciate any links!

This is a project for a computer graphics class I'm in, we are to make an animation or game or do a research paper, and I chose to make a game (duh). Anyway, I created a 3d world that you can fly around in using opengl on a linux machine.

The problem is that when I push a key to move, there's a slight delay before you actually start moving, maybe half a second at the most. It's especially annoying when I'm moving forward and then push one of the keys to turn, it works but as soon as I hit the second key it stops moving for half a second and then starts moving again.

Does anyone know what's causing the delay?


ps. I think the NeHe tutorial 10 is about moving in a 3d space but I'm having trouble getting it to run on my computer. It runs on the machines at my school but I'm not going back there until monday :P
Advertisement
Sounds like it might have something to do with how you're capturing key events. I get the feeling your half second delay is the time between when you hold down a key and when the OS starts sending character repeats (like when you hold down 'a' in a text editor, it sends it once, than after a 1/2 to 1 second it starts spamming 'aaaaaaaaa' until you release.

I'm not that familiar with linux input events, but that sounds like a culprit to me. Are you capturing keyup/keydown messages and setting a state off of that, or are you just moving anytime you get a keydown message?
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game

Sounds like it might have something to do with how you're capturing key events. I get the feeling your half second delay is the time between when you hold down a key and when the OS starts sending character repeats (like when you hold down 'a' in a text editor, it sends it once, than after a 1/2 to 1 second it starts spamming 'aaaaaaaaa' until you release.

I'm not that familiar with linux input events, but that sounds like a culprit to me. Are you capturing keyup/keydown messages and setting a state off of that, or are you just moving anytime you get a keydown message?



I'm capturing keyup/keydown messages. I think you might be right, I noticed when I hit the key it actually moves just a little bit, pauses half a second, and then starts moving again.
Linux input events basically go "KEYDOWN... {pause}, KEYREPEAT, KEYREPEAT, KEYREPEAT, KEYREPEAT, KEYREPEAT, KEYREPEAT, KEYREPEAT,KEYUP"

What you need to do is remember the state of the keys between events and query that state store instead of examining the events themselves.

If you set up a mapping between X keynames ( the ones in the events ) and your interpretation (up, down, left, right etc which you can enumerate as small integers), then you can have a small array to store the keystates.

The event interpretation then just puts a 1 or 0 in the appropriate array slot for up and down. Ignore the keyrepeats.

There are TWO important gotchas here. One is obvious and one isn't.

The first is that X11 doesn't actually conveniently send you a keyrepeat code for you to ignore. Why it doesn't I don't know but hacky bodging seems likely.

So what you get is a "keyup/keydown" pair of events.

Your options here are just use them as they are or to find the repeat and deliberately ignore it.

If you process ALL pending events between frames, chances are you'll always process both parts and your state array will still hold a "1" for key down, and then everything "just works"

If you timelimit or countlimit your event handling, you may not process both halves, so you need to check if an UP is really an up or part of a repeat. The way to test that (and hence whether to discard) is to take the event, and if it's a keyup peek at the next one. If that's a keydown for the same key AND has the same timestamp as your keyup then you've got a repeat and you can bin them both.

{Technically you're supposed to go on a crawl of the event stack because there technically might be an event in between, but a) that's a pain to do because it needs predicate routines and void casts and nasty stuff like that and b) it's usually never the case on local servers.}


Your second gotcha is the focus. If you lose keyboard focus, you will not get key up events. Hence -- press the button, hold it, click mouse outside the window, release key.... and you'll never see the up event because it went to another window and in this new world of processing state and not events, that's a perpetual turn.

There are two fixes -- the easy way and the technically correct way. The latter is to use a keyboard grab. I wouldn't bother if I were you. Do the easy thing; catch the "lost focus" event (which you WILL get as you click) and clear down your state array at that point ending the movement. It'll be good enough while you're developing and it's less likely to lead to tears than keyboard grabs.

This topic is closed to new replies.

Advertisement