KeyDown turns into KeyHit bug

Archives Forums/BlitzMax Bug Reports/KeyDown turns into KeyHit bug

(tu) ENAY(Posted 2007) [#1]
This bug is dead simple, I'm trying to detect whether or not a SHIFT+A key or just A key is being pressed.
Here is the code:-

Graphics 400,400

Global plop:String = "No Key"
Global shiftdown:Int = 0

Repeat
	If KeyDown(KEY_LSHIFT) Or KeyDown(KEY_RSHIFT) Then
		shiftdown = 1
	Else
		shiftdown = 0
	EndIf
	
	If KeyHit(KEY_A) Then
		Select shiftdown
		Case 0;plop = "Lowercase A"
		Case 1;plop = "Uppercase A"
		End Select
	EndIf
	
	FlushKeys()
		
	Cls
	DrawText "KEY = "+plop,50,50
	DrawText "SHIFT ="+shiftdown,50,70
	Flip
Until KeyDown(KEY_ESCAPE)

End


For some reason detecting the shift keys is going to keyhit, which if you bash both shift and A together, sometimes you will get a capital A.

If I take FlushKeys out then everything works fine, but this is stupid as I am calling FlushKeys AFTER all my key checks.

Here is the exact same code working fine in oldskool Blitz.

Graphics 400,400,0,2

Global plop$ = "No Key"
Global shiftdown = 0

Repeat
	If KeyDown(42) Or KeyDown(54) Then
		shiftdown = 1
	Else
		shiftdown = 0		
	EndIf
	
	If KeyHit(30) Then
		Select shiftdown
		Case 0:plop = "Lowercase A"
		Case 1:plop = "Uppercase A"
		End Select
	EndIf
	
	FlushKeys()
	
	Cls
	Text 50,50,"KEY = "+plop
	Text 50,70,"SHIFT ="+shiftdown
	Flip
Until KeyDown(1)

End



FOODy(Posted 2007) [#2]
It's simple:
[...]
If KeyDown(KEY_LSHIFT) Or KeyDown(KEY_RSHIFT) Then
	shiftdown = 1
Else
	shiftdown = 0		
EndIf
[...]

After the FlushKey()-call KeyDown(KEY_LSHIFT) and KeyDown(KEY_RSHIFT) return False because neither of the keys is 'pressed' anymore. (And shiftdown is set to 0 again)


FOODy


(tu) ENAY(Posted 2007) [#3]
As far as I understand it. As the keyboard is continually being polled, keyhit returns how many times a key has been pressed or if it has been pressed at least once and keydown checks whether the key is held down. Hence their names.

Flush keys should be deleting all record of keys being pressed. But since I'm holding the key down, it shouldn't matter how many times or where you flushkeys because the next time I check Keydown I am still holding the 'key down'.
So flushkeys shouldn't be affecting it.

If you run the Blitz3D/+ code the behaviour works as I would expect it too. Whether I am holding the shift key or not it always stays as either 0 or 1. In BMax it goes to 1 for a split second, so it behaving no different to keyhit.
Whether this is a bug or not, both programs behave differently and at the moment I'd consider this to be a bug in Blitzmax because you shouldn't be able to flush the keys down because they are still being pressed, or maybe this a bug in Blitz3D instead?


TomToad(Posted 2007) [#4]
Looking at the source, when BMax receives an EVENT_KEYDOWN, it sets a flag for that key, then when bmax recieves an EVENT_KEYUP, it resets the flag showing it's no longer being pressed. When you call KeyDown() it simply returns the state of the flag.
The problem comes with the FlushKeys() function
Function FlushKeys()
	PollSystem
	charGet=0
	charPut=0
	For Local i=0 Until 256
		keyStates[i]=0
		keyHits[i]=0
	Next
End Function

KeyStates[] is where the state of the keypress is being placed and as you can see, it resets all the keys to 0.
I would consider this a bug since KeyDown() should properly display the state of the key at all times. Maybe there could be a flag set as to whether or not FlushKeys resets KeyDown() info. Something like this?
Function FlushKeys(Reset:Int = False)
	PollSystem
	charGet=0
	charPut=0
	For Local i=0 Until 256
		If Reset Then keyStates[i]=0
		keyHits[i]=0
	Next
End Function



Russell(Posted 2007) [#5]
What stinks is that KeyDown() is not really what I would call a 'low level' hardware check of the keyboard status. I'm sure this was necessary on some level to make cross-platform conformity easier, but a true signal checking of the keys' status would be very welcome (and probably much faster, too, for games). Granted, OSes tend to make it difficult to access anything at the hardware level anymore, unless you're writing a driver of some kind (which I understand is a pain in the a**).

Anyway, sometimes I find it necessary to put in a line like "Repeat Until Not KeyDown(KEY_WHATEVER)" at the end of a function so that a keypress does not register in the main loop when you don't want it to, if that makes any sense to you....

Russell


remz(Posted 2007) [#6]
Hi,
How about remove FlushKeys() from your code entirely?
Why would you need to call it in the first place? Without it, KeyDown() works exactly as intended: it returns if the key is down at the moment.