Trying to understand keyhit function
#1
Trying to get my tiny brain around the _keyhit command... It seems to switch to the negative key value when the key is released, but with this simple piece, it seems to have retained its positive value. Where am I going wrong?
Code: (Select All)
Color 0, 15: Cls
Message:
k = 0 '                       I need this because _keyhit retains its positive (key pressed) value
Print "Press A or B"

Do Until k > 0 '              do this until _keyhit is positive
    k = _KeyHit '             set k to _keyhit value
Loop
'                             now leave loop with k set at positive value from _keyhit
Select Case k
    Case Is = 65, 97 '        "A" pressed
        ResponseA
    Case Is = 66, 98 '        "B" pressed
        ResponseB
    Case Else
        WrongKey
End Select
Cls
GoTo Message

Sub ResponseA
    Print "A pressed"
    Sleep 1
End Sub

Sub ResponseB
    Print "B pressed"
    Sleep 1
End Sub

Sub WrongKey
    Print "Wrong Key!"
    Sleep 1
End Sub
Reply
#2
(08-09-2022, 02:52 AM)PhilOfPerth Wrote: Trying to get my tiny brain around the _keyhit command... It seems to switch to the negative key value when the key is released, but with this simple piece, it seems to have retained its positive value. Where am I going wrong?
Code: (Select All)
Color 0, 15: Cls
Message:
k = 0 '                       I need this because _keyhit retains its positive (key pressed) value
Print "Press A or B"

Do Until k > 0 '              do this until _keyhit is positive
    k = _KeyHit '             set k to _keyhit value
Loop
'                             now leave loop with k set at positive value from _keyhit
Select Case k
    Case Is = 65, 97 '        "A" pressed
        ResponseA
    Case Is = 66, 98 '        "B" pressed
        ResponseB
    Case Else
        WrongKey
End Select
Cls
GoTo Message

Sub ResponseA
    Print "A pressed"
    Sleep 1
End Sub

Sub ResponseB
    Print "B pressed"
    Sleep 1
End Sub

Sub WrongKey
    Print "Wrong Key!"
    Sleep 1
End Sub

You're checking the value of "k" instead of the function. In "Select Case" clause. It's because you have it on a loop and on second execution, without "k = 0" before it gets to "Do Until k > 0" which causes it to never execute the body of that loop.
Reply
#3
You could simply change your loop and correct most of the issue here:

Code: (Select All)
Do
    k = _KeyHit '             set k to _keyhit value
Loop Until k > 0 '              do this until _keyhit is positive
'                             now leave loop with k set at positive value from _keyhit

Before, what you were doing was a check at the start of the loop to see if k was positive.  Without manually resetting it with each pass, it's going to retain the value that it had from the previous pass, which means it would've stayed positive from the last run, and then skipped over that DO UNTIL k > 0 .... LOOP.

A few pointers that I'd stick in this type of example though:

Code: (Select All)
Do
    k = _KeyHit '             set k to _keyhit value
    _LIMIT 60 '         add a limit here so that your CPU doesn't go into an endless loop and run hot while waiting for a keypress
Loop Until k > 0 '              do this until _keyhit is positive
'                             now leave loop with k set at positive value from _keyhit

As in the small code above, ,add in a limit to reduce CPU usage.  Checking for a keyhit 60 times per second is more than enough.  I honestly doubt your OS will report key events at that rate to begin with!  There's no real reason to create an unthrottled loop here, just to eat up CPU cycles and heat up your PC and wrap up resources.

Note 2, I'd also add in a _KEYCLEAR before that final GOTO statement.  SLEEP doesn't clear keyboard buffers, and the various key input commands usually stack keypresses in a buffer.  If an user holds down the "A" key for several seconds, your loop only processes one keyhit out of the buffer with each pass it makes, which will end up with it processing multiple times after the user lets up on the key!  You're very likely to see your program end up developing a backlog of keypresses which it has to clear out from the buffer, causing lag and odd behavior in it.  By adding a _KEYCLEAR manually into your program, you make certain that issue goes away before it ever becomes a problem.  It basically turns the program here into one that is processing *current* key events and not *buffered* key events -- which seems to be what you'd prefer for it to be doing in this type of demo with SLEEP introducing a second long delay to things.
Reply
#4
Ah, light at the end of the tunnel!
There were several things wrong with my code, and I think they're all covered by these two answers. I didn't know about _keyclear, although I have used clear input in other places. And the _limit thing - well, I never was one for wasting stuff, so if I can save a bit of energy (and CPU wear) with this, I'd better get on board. Thanks again.  Big Grin
Reply




Users browsing this thread: 2 Guest(s)