Keyboard input as soon as its pressed?!?!

Started by
7 comments, last by Tamior 18 years, 8 months ago
Im creating a 3D engine at the moment and I can walk around, but if i press forward, it doesnt move straight away, it delays for a split second then moves forward (Keyboard polling I think its called). How can I fix this so as soon as i press the button it moves with no delay? Thx
Advertisement
If you are programming in Win32 you can find this code of mine usefull
(sorry for mixed comments )

This is the declaration file (.h)

/// @brief Gestisce input tastieraclass KeyBoardState{public:		typedef SHORT	WINKEYBSTATE[256];	typedef SHORT*	LPWINKEYBSTATE;	/// @brief true if key down	inline bool KeyDown(BYTE vkey)const{		return KeyDown(pck,vkey);	}	/// @brief true if key up	inline bool KeyUp(BYTE vkey)const{		return KeyUp(pck,vkey);	}	/// @brief true if key pressed	inline bool KeyPressed(BYTE vkey)const{		return KeyUp(pok,vkey) && KeyDown(pck,vkey);	}	/// @brief true if key released	inline bool KeyReleased(BYTE vkey)const{		return KeyDown(pok,vkey) && KeyUp(pck,vkey);	}	/// @brief void ctor	KeyBoardState(void);		/// @brief Read new state (call this each 'frame')	void Read(void);		/// Reset	void Reset(void);	/// @brief Legge lo stato di tutti i tasti	void GetKeyboardState(LPWINKEYBSTATE pks);	/// @brief Funzione base 	static inline SHORT GetKeyState(BYTE vkey){		return(GetAsyncKeyState(vkey));	}	/// @brief Converte in carattere (minuscolo)	/// Se -1 -> nessuna traduzione possibile	static inline UINT ToChar(BYTE vkey){		return((unsigned char)MapVirtualKey(vkey,2));	}	/// @brief Converte vkey	static inline SHORT ToVkey(unsigned char ch){		return((BYTE)VkKeyScan(ch));	}	/// @brief Traduce il char nel vkey code	static unsigned char CharToVK(char ch){		return (unsigned char)VkKeyScan((TCHAR)ch);	}private:		inline bool KeyDown(LPWINKEYBSTATE pk, BYTE vkey)const{		return (pk[vkey]&DOWNMASK)!=0;	}	inline bool KeyUp(LPWINKEYBSTATE pk, BYTE vkey)const{		return !KeyDown(pk,vkey);	}	LPWINKEYBSTATE pck; // current keyboard	LPWINKEYBSTATE pok; // old (previous) keyboard		WINKEYBSTATE ks1; // buffer1 for kstate	WINKEYBSTATE ks2; // buffer2 for kstate	static const SHORT DOWNMASK;};


This is the rest of the implementation (.cpp file)

// key down -> MSB short true const SHORT KeyBoardState::DOWNMASK = (SHORT)(1<<(8*sizeof(SHORT)-1));// ctorKeyBoardState::KeyBoardState(void){	GetKeyboardState(ks1);	memcpy(ks2,ks1,sizeof(WINKEYBSTATE));	pck = ks1;	pok = ks2;}	// readvoid KeyBoardState::Read(void){	// AC::Swap(pck,pok); swap pointers pck <--> pok	LPWINKEYBSTATE tmp = pck; 	pck = pok; pok = tmp;  this->GetKeyboardState(pck);}// acquisisce stato su pks  (static)void KeyBoardState::GetKeyboardState(LPWINKEYBSTATE pks){	for(int vk=0;vk<256; vk++)		pks[vk]=this->GetKeyState(vk);}// resetvoid KeyBoardState::Reset(void){	memset(pck,0,256*sizeof(SHORT));	memset(pok,0,256*sizeof(SHORT));}	



Usage:

Simply create an histance of the class in your main class or create it as static(or global).
Then each frame simply call the method Read()
Then you can use the functions Key[Up][Down][Pressed][Release] to retrieve current
state. The id of the key is the virtual code...you can find virtual codes in your help (ie: VK_ESCAPE, VK_DOWN, VK_UP,...) or find VK_ in your windows header files

(pseudo) simple example
...KeyBoardState _ks;...void main(void){  while(loop)  {    _ks.Read();        if(_ks.KeyDown(VK_UP)) goForward();       // while UP is down        if(_ks.KeyPressed(VK_F9)) TakeSnapShot(); // once        RenderSomething();  }}


I'va also implemented functions to manage key names and descriptions but for brevity I've removed them.

I hope this will be useful for you.
im using linux to create it, but Ill have a look if I can change yours.

Anyone have a linux method that works?

Thx
Linux??? Ooops sorry :)

However I'm sure you should have similar low level functions to retrieve (asyncronous) keyboard state.
The trick as you can see is to store the previous and the current state and compare them (if you need only to track up/down states you could resolve with a single function)
Well i have:
static void key(unsigned char k, int x, int y){    switch (k)   {        case 27:		      exit(0);      break;    case 'w':      Camera.moveForward();      break;    case 'd':	      ...      ...      ...  }  // Refresh the Window  glutPostRedisplay();}

This recognises the key is pressed straight away and moves once, then a short delay (I have my finger pressed on "w") Then it moves forward, but I want it so when you press it, it moves forward steadily until I let go.

I read somewhere this problem is due to frame based rendering instead of time based rendering.

Any Ideas?
There are 2 different types of messages from the keyboard. First is "key is pressed", second is "key released". In different API's there are different ways of telling whether the key is pressed or released. In glut for example there are 2 callback functions glutKeyboardFunc and glutKeyboardUpFunc respectivly, in Windows API there are just 2 different types of message from WndProc. There should be a well known alternative in Linux. Thes easiest way to implement action without delay on pressing a key is to have boolean variables for keys that are used. When the program catches the event of pressing a key it should set the variable 'true'. And when it catches the event of releasing a key, variable should be 'false'. And each iteration of the main cycle the function responsible for the action should check the variable before implementation. It's that easy.
Ill have a go, ill get back to ya...
Thats great! So simple and so effective!

Thanks alot mate.
Glad I could help :)

This topic is closed to new replies.

Advertisement