Movement lag?

Started by
11 comments, last by Noods 21 years, 7 months ago
I am having a issue with movement in my game and I was wondering if anyone had similar problems. I am creating Pong with simple controls. up makes it go up down makes it go down. Here is the code I use. Process of the input: case VK_UP: box.move(0,-5); break; case VK_DOWN: box.move(0,5); break; Method to "move" the box: void CObject::move(int xmove, int ymove) { yaxis = yaxis + ymove; } The problem is, when I hold down either up or down, the "paddle" moves 5 pixles, stays idle for a second, then starts a continuous move in the direction I told it to go. The controls overall work properly, but I am wondering what is causing that little lag when I first hold in the key. Any ideas? Thanks in advance!
Advertisement
It is pausing because you are working with key-repeats. When you hold the key down, the OS sends repetative key-pressed messages to the program. It takes a moment before this kicks in, so you can type normally and not worry about holding the button down too long.

The correct solution would be to base the movement on the time interval. Basically, when the key is pressed you set a velocity. When it is released, remove the velocity (make it 0). Every frame, move the object time_since_last_frame*velocity.
The best way to fix that is to create a keyboard buffer which is an array of 256 BOOL''s.

BOOL keyBuffer[256];

The 256 values represent the scan codes of the keys on your keyboard, thus making it easy to use the VK_ constants as index to this keyboard buffer.

To get some functionality into this keyboard buffer array you have to intercept the WM_KEYDOWN and WM_KEYUP messages. The wParam parameter for those messages represents the scan code value of the key pressed.

Therefore, on WM_KEYDOWN you mark the corresponding key in the keyboard buffer as TRUE, and on WM_KEYUP you mark it as FALSE.

e.g. case WM_KEYDOWN: keyBuffer[wParam] = TRUE; break;
case WM_KEYUP: keyBuffer[wParam] = FALSE; break;


Now you are all set to go.

You have to make keyBuffer global if you want to use it in the entirety of your program.

Once it''s declared as global, anywhere in the program you can do this:

if (keyBuffer[VK_UP])
box.move(-5);
else if (keyBuffer[VK_DOWN])
box.move(5);

...

CBox::move(int dy)
{
m_box.y += dy;
}

This will make up for a very smooth movement.

If you want PRECISION you have to use DirectInput which is a bit more complex and is not part of the Win32 API.

Hope this helps!

-G|aD-
Ill actually be using a key buffer in my next program, but it is something I dont want to use here.

Deyja, what you described is actuall exactly what I want. Really, I had that exact code set up but I couldnt find a way to tell when the user released the key, and I didnt see any VK flags that would fit the bill. How would I detect the release of the key someone is currently pressing?
quote:
How would I detect the release of the key someone is currently pressing?


Intercept the WM_KEYUP message.

By the way, take a look at the GetAsyncKeyState() function which is a replacement for the keyBuffer() technique w/o having to type all that code.

Good luck!

-G|aD-
OK, I set my key handler to watch for the WM_KEYUP, but it just acts like it never sees it. I checked all my arguments and they are all correct. It lets me compile fine...I swear its just like I never get that message. Any ideas?
My key code looks like this (Barely changed from NeHe''s original code.


  case WM_KEYDOWN:					// Is A Key Being Held Down?		{			theGame->SendKeyPress(wParam);			return 0;								// Jump Back		}		case WM_KEYUP:								// Has A Key Been Released?		{			theGame->SendKeyRelease(wParam);			return 0;								// Jump Back		}  


Inside class ''Game'' I have


  JMerror Game::SendKeyPress(JMuint8 key){	if (key > 255) return JMbad_key;	keys[key] = true;	return JMno_error;}JMerror Game::SendKeyRelease(JMuint8 key) {	if (key > 255) return JMbad_key;	keys[key] = false;	return JMno_error;}  


Of course; you would probably want to just plop the keys array into the main program. In the main game loop, you have ''if(keys[VK_DOWN]) object.move(object.velocity*time_passed);''

You should also check to make sure they aren''t pressing opposite keys - for instance, if they are pressing up AND down, nothing happens. So, if up is pressed, ignore it when you get the keypressed message for down.
I narrowed it down even more. I put a case for WM_KEYDOWN in my code and it didnt detect that either. It seems that the problem is, is that my program just isnt seeing any of the "WM" messages. Anyone know why this would happen?
If it wasn''t seeing any WM messages (WM means ''Windows Message''. Never would have quessed that, eh?) it wouldn''t be getting the WM_KEYDOWN message either. Post the message handling code.
I''m supposing you have a PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) which doesn''t let messages get on your window''s queue therefore your program doesn''t see them.

Anyways...the only way to find out is if you post your main loop code.

-G|aD-

This topic is closed to new replies.

Advertisement