Using keycode detection

BlitzMax Forums/BlitzMax Beginners Area/Using keycode detection

Emmett(Posted 2005) [#1]
I was learning about keycode detection and discovered that the way it is being used in this code snippet causes unexpected behavior.
Strict
Graphics 640,480
HideMouse
Repeat
Cls
If KeyHit(key_return)=False
	DrawText "Return key for action -",100,240
	DrawText "Escape key to exit.",100,255
	If KeyHit(key_return) '<- This works after a few taps but KeyDown(key_return) works very well.
		Cls
		SetColor 0,255,0
		DrawText "Return Key hit, now going to TheLoop().",100,240
		Flip
		Delay 1700
		TheLoop()
	EndIf
EndIf
Flip
Until KeyHit(key_escape)

Function TheLoop()
Local x, x1
Repeat
	For x=30 To 200
		If KeyHit(key_space) Return
		Cls
		SetColor -x,-x,255
		DrawOval x,x,x,x
		SetColor 255,255,255
		DrawText"Hit space key to get back to main loop",x,x+x
		Flip
	Next
	For x1=x To 30 Step-3
		If KeyHit(key_space) Return
		Cls
		SetColor 255,-x1,-x1
		DrawOval x1,x1,x1,x1
		SetColor 255,255,255
		DrawText"Hit space key to get back to main loop",x1,x1+x1
		Flip
	Next
Until KeyHit(key_space)
End Function

Of course I will avoid using keycodes in this way but was curious as to why it works badly.


PowerPC603(Posted 2005) [#2]
This works better:
Repeat
	Cls

	local ReturnKeyHit = KeyHit(key_return) ' Get status of the return key once per loop

	If ReturnKeyHit=False ' Check the status of the return key (has it been pressed?)
		DrawText "Return key for action -",100,240
		DrawText "Escape key to exit.",100,255
	EndIf

	If ReturnKeyHit ' Check the key again
		Cls
		SetColor 0,255,0
		DrawText "Return Key hit, now going to TheLoop().",100,240
		Flip
		Delay 1700
		TheLoop()
	EndIf

	Flip
Until KeyHit(key_escape)


When you call KeyHit, it retrieves the status of the given key and flushes the status of that key afterwards, to avoid problems.

See this:
Imagine you're writing a program that prints one line, every time you press the spacebar.
If the key wouldn't get flushed after checking it's status, then after one hit on that key, your program would run forever, without you pressing any keys.
Graphics 640, 480, 0

Start = MilliSecs()

Repeat
	If KeyHit(key_space)
		Print "You pressed the spacebar" 'Prints in the IDE's output window
	endif
Until MilliSecs() > (Start + 5000)

Take this example.
It runs for 5 seconds.
If you press the spacebar, it would print the given statement.
If you press again, it will print another statement.
If the keyboard matrix wasn't flushed (only the status of the spacebar key will be flushed when using keyhit(key_space)), it would print the statement until the program ends (after 5 seconds after startup).

To be able to use your loop, you'll have to press the return key twice in a loop, because you're checking it's status twice in one loop.
I couldn't get your example to work on my system, because the loop was running faster than I could press the return key twice.

Now this new loop stores the status of your return key in a variable and then it checks this variable for getting the status of the return key per loop.


Emmett(Posted 2005) [#3]
Thanks PowerPC603 -
Thats why my code works if you rapidly tap the return key because the keyboard matrix receives the second keyhit during the time it took to draw the two lines of text.
The code checks the If statements once per repeat/until sequence.
In your example: As long as the KeyHit remains False the 1st If gets processed.
When Keyhit is True only the 2nd If gets processed. AhHa Yea Much Better!


PowerPC603(Posted 2005) [#4]

Thats why my code works if you rapidly tap the return key because the keyboard matrix receives the second keyhit during the time it took to draw the two lines of text.


You could get lucky if you pressed the spacebar only once, but during the drawing of the two lines of text.

I saw this approach (using a variable for keyhit) in a topic for B3D a long time ago, they had the same problem.