Author Topic: Keyboard tragedy.  (Read 6945 times)

0 Members and 1 Guest are viewing this topic.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Keyboard tragedy.
« on: April 18, 2009 »
Im trying to get a keyboard library similar to the style of Blitz Basic, with using GetAsyncKeyState(Keycode) And 32768. And will try and put into words what should be happening.

Im using flushkeys to stop you being able to repeatedly hold whatever key is being pressed, so that once you've pressed that key it resets as if no key has been pressed, even if you are holding it down; aka Keyhit()

I would also like to add in, KeyDown() which lets you hold that key to your hearts desire.

Maybe there are other commands similar to GetASyncKeyState.

Code: [Select]
'
' Lib - Keyboard
' Version 1.0.0
'
Const KEYS_ON=0
Const KEYS_OFF=1

Dim Shared As Integer Keys=KEYS_ON, KeyDelay=450
Dim Shared As Single KeyboardTimer=0, RunningTime

Sub FlushKeys()

    If ( KeyboardTimer + KeyDelay ) <= Millisecs( RunningTime ) Then
        Keys=KEYS_ON
    Else
        Keys=KEYS_OFF
    End if

End Sub

Function KeyHit( ByVal KeyChar As Integer ) As Integer
   
    If Keys=KEYS_ON Then
       
        If (GetAsyncKeyState(KeyChar) And -32768) Then
            KeyboardTimer=Millisecs( RunningTime ) 
            Return True
        Else
            Return False
        End If
       
    End If
   
End Function

Little example of how im calling stuff:
Code: [Select]
    KeyboardTimer=millisecs( Timer )' i use a function to return timezed 1000, KeyboardTimer=Timer*1000'
   
    While Keyhit(VK_Escape)<>True
       
        ClearScreen()

        RunningTime=Timer()

        If Keyhit(VK_LButton)=True Then Show=Not Show
       
        If Show Then
            Print"Booooooooooo!!!!!!!!!!!!"
        End if
       
        FlushKeys()
       
Wend

Have a re-giggle, small favour please keep the time methods to being in millisecs just that its something im used to. Blame Blitz for that :D

Cheers and hope you can sort me out of my misery,
Clyde.
« Last Edit: April 18, 2009 by Clyde »
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Keyboard tragedy.
« Reply #1 on: April 18, 2009 »
You need to set Keys=KEYS_OFF the moment you've read a key.

If Keys=KEYS_ON Then
       
        If (GetAsyncKeyState(KeyChar) And -32768) Then
            KeyboardTimer=Millisecs( RunningTime ) 
...
Keys = KEYS_OFF
...
            Return True
        Else
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Keyboard tragedy.
« Reply #2 on: April 18, 2009 »
Thanks Jim, added that but It still wants to continue with the key being pressed. what it does, for example hold the leftmousebutton ( VK_LBUTTON ), and you'll witness it toggling between the state of when to print "Booo" ( or if you use it to do something else ) or not.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Keyboard tragedy.
« Reply #3 on: April 20, 2009 »
Take a look at the ScreenEvent function. It will tell you the current state of the keys, i.e. the current key values and the state of the mouse. In the case you mentioned, it will return EVENT_KEY_REPEAT when a key is repeated.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Keyboard tragedy.
« Reply #4 on: April 20, 2009 »
Cool dude, what inc is that in?
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Keyboard tragedy.
« Reply #5 on: April 20, 2009 »
It is in fbgfx.bi in the namespace fb.


Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Keyboard tragedy.
« Reply #6 on: April 21, 2009 »
Cheers mate, Im hoping to avoid having to include the fbgfx stuff as it makes for bigger executable files. Perhaps this will give more of an insight into the key problem.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Keyboard tragedy.
« Reply #7 on: April 28, 2009 »
Ok, still no joys with this and i'd love to get it sorted, so I can move on to other things.
There must be something to empty out the keyboard buffer / poll events for Keyhit(), so somone cant hold the key down ;) you must of witnessed using (GetAsyncKeyState(KeyChar) And -32768) that it carries on regardless with the action applied to the the keys task.

Ive looked through the winuser.bi but havent seen anything to accomplish this; well anything that sticks out like a sore thumb. I know Jim did a readkeyboard sub in his Sidtest2, and  that had a time delay before calling readkeyboard(); but that worked by not allowing if the song was allready selected.

I am using Freebasic and tinyptc_ext, so no gfxlib stuff please.

This is the key function stripped of any timer stuff; and just return true or false if a keyshit

Code: [Select]
Function KeyHit( ByVal KeyChar As Integer ) As Integer
   
    If (GetAsyncKeyState(KeyChar) And -32768) Then
        Return True
    Else
        Return False
    End If
       
End Function
Thanks for your time and assistance,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Keyboard tragedy.
« Reply #8 on: April 28, 2009 »
There really aren't any more Windows functions for the keyboard, unless you go to use DirectInput, which I always found to be flakey.
The reason is that GetAsyncKeyState isn't what anyone uses for keyboard input in real applications.  In Windows you would sit and wait for WM_KEYUP and WM_KEYDOWN messages in your Windows proc.
How I deal with it then is:
For each WM_KEYDOWN, set a value in an array for, ie.  keys[pressed_key]=1
For each WM_KEYUP, clear a value in the array for, ie.  keys[pressed_key]=0
Then when I want to know about keys I look in the array.

Of course, you can't do this with GetAsyncKeyState because it only reads one key at a time...

You want a key that won't repeat, right?

X_currently_pressed = false;
X_was_pressed = false;
...
Sub ReadKeyboard()

if GetAsyncKeyState('X') & -32768 then
 if X_currently_pressed == true then
   X_was_pressed = false
 else
   X_was_pressed = true
  end if
 X_currently_pressed = true;
else
 X_currently_pressed = false;
 X_was_pressed = false;
end if

End Sub


Now you call ReadKeyboard very regularly (each frame).  If you want to know about X, then look at X_was_pressed to see if the key has gone down since the last time, and X_currently_pressed to see if it is down now.

Jim
« Last Edit: April 28, 2009 by Jim »
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Keyboard tragedy.
« Reply #9 on: April 28, 2009 »
Thanks Jim, I will make a test program to go with that.

What your recommending is that I'd be best of using something like inkey? I was avoiding this incase it pulled in and included the fbgfx lib stuff into tinyptc programs. Am I safe of this not happening, does anybody know?

Cheers once again,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Keyboard tragedy.
« Reply #10 on: April 28, 2009 »
A bit more background for you.  The reason that Windows doesn't do this for you is because it's a multitasking OS.  There's only one keyboard but lots of running applications.  If they all flushed the keyboard no-one would see anything get pressed.

I doubt using Inkey is going to be any better or worse than GetAsyncKeyState.  They do the same thing.

Jim
PS, I just edited my pseudo code above.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Keyboard tragedy.
« Reply #11 on: April 28, 2009 »
Here it is implemented in Blitz using KeyDown(45) instead of GetAsyncKeyState('X')AND-32768
Code: [Select]
Global X_currently_pressed = False
Global X_was_pressed = False

Repeat
Flip

Cls
ReadKeyboard()

Locate 0,0
Print "Down="+X_was_pressed+" Held="+X_currently_pressed

If X_was_pressed Then z=z+1
Print z

Until KeyDown(1)
End

Function ReadKeyboard()

If KeyDown(45) Then
 If X_currently_pressed = True Then
   X_was_pressed = False
 Else
   X_was_pressed = True
  End If
 X_currently_pressed = True
Else
 X_currently_pressed = False
 X_was_pressed = False
End If

End Function

Challenge Trophies Won:

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: Keyboard tragedy.
« Reply #12 on: April 29, 2009 »
The correct way to do that is checking the value returned by GetAsyncKeyState function and you don't need to use "AND" operator. The correct value to check is -32767 and not -32768

Check out the example below, it works fine :)

Code: [Select]
'
' Lib - Keyboard
' Version 1.0.0
'

#Include Once "Windows.bi"

dim shared Show as integer

Function KeyHit( ByVal KeyChar As Integer ) As Integer
   
    If (GetAsyncKeyState(KeyChar) = -32767) Then
        Return True
    Else
        Return False
    End If
       
End Function

    While Keyhit(VK_Escape)<>True
       
        If Keyhit(VK_LButton)=True Then
            Show=True
        else
            Show=False
        end if
             
        If Show=True Then
            Print"cracked by rbz :)"   
        End if
               
    Wend
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Keyboard tragedy.
« Reply #13 on: April 29, 2009 »
You're not supposed to use bit 1 of the result of GetAsyncKeyState under Win32.  If two applications are using that function then who gets the 'has it changed since last time' bit is random.
http://msdn.microsoft.com/en-us/library/ms646293(VS.85).aspx

It'll probably work :).  Then not work. :P  Then work again :)

Jim
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Keyboard tragedy.
« Reply #14 on: April 29, 2009 »
Thankyou both, really appreciate it. 8)
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won: