Page 1 of 2

okay.. group effort. fixing keyboardinkey...post your fixes

Posted: Thu Jun 29, 2006 3:13 pm
by dracflamloc
Okay everyone knows keyboard inkey is pretty crappy for use in a game when you are trying to implement chatting. It only detects on keyboard RELEASED and isnt 100% accurate with the Shift key down.

Here we should all post our fixes for this problem.

My fix has a problem, that keys repeat way too fast, and the only way to stop that is to change the #KeyTypeDelayMs to something so large you have to type the speed of a 2 year old to not miss key presses.

Here it is, see if you can fix it or if you already have a working one just post it:

Code: Select all

Procedure.s GetKeyboardASCII()
  kchar.s=""
  
  If ElapsedMilliseconds()-lastKeyTypeMs >= #KeyTypeDelayMs
    If KeyboardPushed(#PB_Key_0) Or KeyboardPushed(#PB_Key_Pad0)
      kchar="0"
    ElseIf KeyboardPushed(#PB_Key_1) Or KeyboardPushed(#PB_Key_Pad1)
      kchar="1"
    ElseIf KeyboardPushed(#PB_Key_2) Or KeyboardPushed(#PB_Key_Pad2)
      kchar="2"
    ElseIf KeyboardPushed(#PB_Key_3) Or KeyboardPushed(#PB_Key_Pad3)
      kchar="3"
    ElseIf KeyboardPushed(#PB_Key_4) Or KeyboardPushed(#PB_Key_Pad4)
      kchar="4"
    ElseIf KeyboardPushed(#PB_Key_5) Or KeyboardPushed(#PB_Key_Pad5)
      kchar="5"
    ElseIf KeyboardPushed(#PB_Key_6) Or KeyboardPushed(#PB_Key_Pad6)
      kchar="6"
    ElseIf KeyboardPushed(#PB_Key_7) Or KeyboardPushed(#PB_Key_Pad7)
      kchar="7"
    ElseIf KeyboardPushed(#PB_Key_8) Or KeyboardPushed(#PB_Key_Pad8)
      kchar="8"
    ElseIf KeyboardPushed(#PB_Key_9) Or KeyboardPushed(#PB_Key_Pad9)
      kchar="9"
    ElseIf KeyboardPushed(#PB_Key_Minus)
      kchar="-"
    ElseIf KeyboardPushed(#PB_Key_Equals)
      kchar="="
    ElseIf KeyboardPushed(#PB_Key_Slash)
      kchar="/"
    ElseIf KeyboardPushed(#PB_Key_BackSlash)
      kchar="\"
    ElseIf KeyboardPushed(#PB_Key_LeftBracket)
      kchar="["
    ElseIf KeyboardPushed(#PB_Key_RightBracket)
      kchar="]"
    ElseIf KeyboardPushed(#PB_Key_SemiColon)
      kchar=";"
    ElseIf KeyboardPushed(#PB_Key_Apostrophe)
      kchar="'"
    ElseIf KeyboardPushed(#PB_Key_Period) Or KeyboardPushed(#PB_Key_PadComma)
      kchar="."
    ElseIf KeyboardPushed(#PB_Key_Comma)
      kchar=","
    ElseIf KeyboardPushed(#PB_Key_Q)
      kchar="q"
    ElseIf KeyboardPushed(#PB_Key_W)
      kchar="w"
    ElseIf KeyboardPushed(#PB_Key_E)
      kchar="e"
    ElseIf KeyboardPushed(#PB_Key_R)
      kchar="r"
    ElseIf KeyboardPushed(#PB_Key_T)
      kchar="t"
    ElseIf KeyboardPushed(#PB_Key_Y)
      kchar="y"
    ElseIf KeyboardPushed(#PB_Key_U)
      kchar="u"
    ElseIf KeyboardPushed(#PB_Key_I)
      kchar="i"
    ElseIf KeyboardPushed(#PB_Key_O)
      kchar="o"
    ElseIf KeyboardPushed(#PB_Key_P)
      kchar="p"
    ElseIf KeyboardPushed(#PB_Key_A)
      kchar="a"
    ElseIf KeyboardPushed(#PB_Key_S)
      kchar="s"
    ElseIf KeyboardPushed(#PB_Key_D)
      kchar="d"
    ElseIf KeyboardPushed(#PB_Key_F)
      kchar="f"
    ElseIf KeyboardPushed(#PB_Key_G)
      kchar="g"
    ElseIf KeyboardPushed(#PB_Key_H)
      kchar="h"
    ElseIf KeyboardPushed(#PB_Key_J)
      kchar="j"
    ElseIf KeyboardPushed(#PB_Key_K)
      kchar="k"
    ElseIf KeyboardPushed(#PB_Key_L)
      kchar="l"
    ElseIf KeyboardPushed(#PB_Key_Z)
      kchar="z"
    ElseIf KeyboardPushed(#PB_Key_X)
      kchar="x"
    ElseIf KeyboardPushed(#PB_Key_C)
      kchar="c"
    ElseIf KeyboardPushed(#PB_Key_V)
      kchar="v"
    ElseIf KeyboardPushed(#PB_Key_B)
      kchar="b"
    ElseIf KeyboardPushed(#PB_Key_N)
      kchar="n"
    ElseIf KeyboardPushed(#PB_Key_M)
      kchar="m" 
    ElseIf KeyboardPushed(#PB_Key_Space)
      kchar=" "      
    EndIf 
  EndIf   
    
  If KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift)
    Select kchar
      Case "/"
        kchar="?"
      Case "."
        kchar=">"
      Case ","
        kchar="<"
      Case ";"
        kchar=":"
      Case "'"
        kchar=Chr(34)
      Case "["
        kchar="{"
      Case "]"
        kchar="}"
      Case "\"
        kchar="|"
      Case "`"
        kchar="~"
      Case "1"
        kchar="!"
      Case "2"
        kchar="@"
      Case "3"
        kchar="#"
      Case "4"
        kchar="$"
      Case "5"
        kchar="%"
      Case "6"
        kchar="^"
      Case "7"
        kchar="&"
      Case "8"
        kchar="*"
      Case "9"
        kchar="("
      Case "0"
        kchar=")"
      Case "-"
        kchar="_"
      Case "="
        kchar="+"
    EndSelect
    
    If Asc(kchar) >= $61 And Asc(kchar) <= $7A
      kchar=UCase(kchar)
    EndIf   
  EndIf 
  
  If kchar<>""
    lastKeyTypeMs=ElapsedMilliseconds()
  EndIf  
  
  ProcedureReturn kchar
EndProcedure
The challenge:
1. Must be 3.94 compatible (Optional 4.0)
2. Must work similar to how normal textgadgets work when detecting each key
3. Must be cross-platform
4. Must detect keypresses on pushed, not released.

[edit] had to disable html in this post

Posted: Thu Jun 29, 2006 3:59 pm
by Fred
What's the problem exactly with the released and chatting ?

Posted: Thu Jun 29, 2006 4:10 pm
by dracflamloc
Its annoying and a-typical for the way normal users work on thier pc when typing and doesnt allow for repeating characters when holding a key down. Also the fact that special cases needed to be added for the shift-key and things like !@#$ etc.

Posted: Thu Jun 29, 2006 4:19 pm
by Fred
On my v4, the @$^ etc. are correctly handled, it was changed during the beta testing. About the repeating stuff, for a chat program i won't see why it's useful. You won't hold down a key during 15 secs unless you want to add some "Ho noooooo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" ;). But that's a good point, i will see if it's possible to handle the repeat thing.

Posted: Thu Jun 29, 2006 4:41 pm
by dracflamloc
Also visual feedback. When people press a key in they expect it to immediately reflect on the screen. With inkey() it only shows on the screen after they've released the key. Perhaps it should be renamed to KeyboardOutkey() :)

Posted: Fri Jun 30, 2006 3:57 am
by netmaestro
You're doing good work there, dracflamloc, you only lack some logic for the timing and a backspace. I made some additions, here's a modified version to try. It includes a little test program at the end:

Code: Select all

Procedure.s GetKeyboardASCII() 

  Static oldkey.s 
  Static timer_on.l 
  Static start.l 

  kchar.s="" 
  If KeyboardPushed(#PB_Key_0) Or KeyboardPushed(#PB_Key_Pad0) 
    kchar="0" 
  ElseIf KeyboardPushed(#PB_Key_1) Or KeyboardPushed(#PB_Key_Pad1) 
    kchar="1" 
  ElseIf KeyboardPushed(#PB_Key_2) Or KeyboardPushed(#PB_Key_Pad2) 
    kchar="2" 
  ElseIf KeyboardPushed(#PB_Key_3) Or KeyboardPushed(#PB_Key_Pad3) 
    kchar="3" 
  ElseIf KeyboardPushed(#PB_Key_4) Or KeyboardPushed(#PB_Key_Pad4) 
    kchar="4" 
  ElseIf KeyboardPushed(#PB_Key_5) Or KeyboardPushed(#PB_Key_Pad5) 
    kchar="5" 
  ElseIf KeyboardPushed(#PB_Key_6) Or KeyboardPushed(#PB_Key_Pad6) 
    kchar="6" 
  ElseIf KeyboardPushed(#PB_Key_7) Or KeyboardPushed(#PB_Key_Pad7) 
    kchar="7" 
  ElseIf KeyboardPushed(#PB_Key_8) Or KeyboardPushed(#PB_Key_Pad8) 
    kchar="8" 
  ElseIf KeyboardPushed(#PB_Key_9) Or KeyboardPushed(#PB_Key_Pad9) 
    kchar="9" 
  ElseIf KeyboardPushed(#PB_Key_Minus) 
    kchar="-" 
  ElseIf KeyboardPushed(#PB_Key_Equals) 
    kchar="=" 
  ElseIf KeyboardPushed(#PB_Key_Slash) 
    kchar="/" 
  ElseIf KeyboardPushed(#PB_Key_BackSlash) 
    kchar="\" 
  ElseIf KeyboardPushed(#PB_Key_LeftBracket) 
    kchar="[" 
  ElseIf KeyboardPushed(#PB_Key_RightBracket) 
    kchar="]" 
  ElseIf KeyboardPushed(#PB_Key_SemiColon) 
    kchar=";" 
  ElseIf KeyboardPushed(#PB_Key_Apostrophe) 
    kchar="'" 
  ElseIf KeyboardPushed(#PB_Key_Period) Or KeyboardPushed(#PB_Key_PadComma) 
    kchar="." 
  ElseIf KeyboardPushed(#PB_Key_Comma) 
    kchar="," 
  ElseIf KeyboardPushed(#PB_Key_Q) 
    kchar="q" 
  ElseIf KeyboardPushed(#PB_Key_W) 
    kchar="w" 
  ElseIf KeyboardPushed(#PB_Key_E) 
    kchar="e" 
  ElseIf KeyboardPushed(#PB_Key_R) 
    kchar="r" 
  ElseIf KeyboardPushed(#PB_Key_T) 
    kchar="t" 
  ElseIf KeyboardPushed(#PB_Key_Y) 
    kchar="y" 
  ElseIf KeyboardPushed(#PB_Key_U) 
    kchar="u" 
  ElseIf KeyboardPushed(#PB_Key_I) 
    kchar="i" 
  ElseIf KeyboardPushed(#PB_Key_O) 
    kchar="o" 
  ElseIf KeyboardPushed(#PB_Key_P) 
    kchar="p" 
  ElseIf KeyboardPushed(#PB_Key_A) 
    kchar="a" 
  ElseIf KeyboardPushed(#PB_Key_S) 
    kchar="s" 
  ElseIf KeyboardPushed(#PB_Key_D) 
    kchar="d" 
  ElseIf KeyboardPushed(#PB_Key_F) 
    kchar="f" 
  ElseIf KeyboardPushed(#PB_Key_G) 
    kchar="g" 
  ElseIf KeyboardPushed(#PB_Key_H) 
    kchar="h" 
  ElseIf KeyboardPushed(#PB_Key_J) 
    kchar="j" 
  ElseIf KeyboardPushed(#PB_Key_K) 
    kchar="k" 
  ElseIf KeyboardPushed(#PB_Key_L) 
    kchar="l" 
  ElseIf KeyboardPushed(#PB_Key_Z) 
    kchar="z" 
  ElseIf KeyboardPushed(#PB_Key_X) 
    kchar="x" 
  ElseIf KeyboardPushed(#PB_Key_C) 
    kchar="c" 
  ElseIf KeyboardPushed(#PB_Key_V) 
    kchar="v" 
  ElseIf KeyboardPushed(#PB_Key_B) 
    kchar="b" 
  ElseIf KeyboardPushed(#PB_Key_N) 
    kchar="n" 
  ElseIf KeyboardPushed(#PB_Key_M) 
    kchar="m" 
  ElseIf KeyboardPushed(#PB_Key_Space) 
    kchar=" " 
  ElseIf KeyboardPushed(#PB_Key_Back) 
    kchar=Chr(14)      
  EndIf 
    
  If KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift) 
    Select kchar 
      Case "/" 
        kchar="?" 
      Case "." 
        kchar=">" 
      Case "," 
        kchar="<" 
      Case ";" 
        kchar=":" 
      Case "'" 
        kchar=Chr(34) 
      Case "[" 
        kchar="{" 
      Case "]" 
        kchar="}" 
      Case "\" 
        kchar="|" 
      Case "`" 
        kchar="~" 
      Case "1" 
        kchar="!" 
      Case "2" 
        kchar="@" 
      Case "3" 
        kchar="#" 
      Case "4" 
        kchar="$" 
      Case "5" 
        kchar="%" 
      Case "6" 
        kchar="^" 
      Case "7" 
        kchar="&" 
      Case "8" 
        kchar="*" 
      Case "9" 
        kchar="(" 
      Case "0" 
        kchar=")" 
      Case "-" 
        kchar="_" 
      Case "=" 
        kchar="+" 
    EndSelect 
    
    If Asc(kchar) >= $61 And Asc(kchar) <= $7A 
      kchar=UCase(kchar) 
    EndIf    
  EndIf 
  
  If UCase(kchar)=UCase(oldkey)
    If timer_on 
      If ElapsedMilliseconds()-start < 700 
        ProcedureReturn "" 
      Else 
        Delay(80) 
        ProcedureReturn kchar 
      EndIf 
    Else 
      timer_on = #True 
      start=ElapsedMilliseconds() 
      ProcedureReturn "" 
    EndIf 
  Else 
    oldkey=kchar 
    timer_on = #False 
    ProcedureReturn kchar 
  EndIf 
  
EndProcedure 

; Test program 

InitSprite():InitKeyboard() 
OpenScreen(800,600,32,"") 
Repeat 
  ExamineKeyboard() 
  tmp.s = GetKeyboardASCII() 
  If tmp <> "" 
    If tmp = Chr(14) ; backspace 
      a$=Left(a$,Len(a$)-1) 
    Else 
      a$+tmp 
    EndIf 
  EndIf 
  ClearScreen(0) 
  StartDrawing(ScreenOutput()) 
    DrawText(50,280, a$ + "_",#White,0) 
  StopDrawing() 
  FlipBuffers() 
  Delay(1) 
Until KeyboardPushed(#PB_Key_Escape) 

End

Re: okay.. group effort. fixing keyboardinkey...post your fi

Posted: Fri Jun 30, 2006 5:36 am
by Phoenix
dracflamloc wrote:

Code: Select all

If KeyboardPushed(#PB_Key_LeftShift) Or KeyboardPushed(#PB_Key_RightShift)
    Select kchar
      Case "/"
        kchar="?"
You know this won't work with different keyboard layouts.... don't you???? The slash key on an English keyboard won't produce a ? on a non-English keyboard.... just something for you to be aware of....

Posted: Fri Jun 30, 2006 5:58 am
by dracflamloc
Yes I know but theres really nothing I can do about that with PBs commandset.

Posted: Fri Jun 30, 2006 6:17 am
by DarkDragon
dracflamloc wrote:Yes I know but theres really nothing I can do about that with PBs commandset.
Receiving the #WM_CHAR windowevent on a screen would help very lot.

Posted: Fri Jun 30, 2006 6:18 am
by dracflamloc
Sure if i was only using windows

Posted: Fri Jun 30, 2006 6:46 am
by DarkDragon
dracflamloc wrote:Sure if i was only using windows
On Linux there's most often a gtk version of the windows api command, like you can see for example here:

http://www.purebasic.fr/english/viewtop ... ousebutton

Posted: Fri Jun 30, 2006 7:40 am
by dracflamloc
Yea I'll probably look that up

Posted: Fri Jun 30, 2006 8:48 am
by netmaestro
I tested the code above on PB 3.94, the procedure itself runs fine but the test program needed a couple minor tweaks. The test program isn't staying with it anyway so I think (-hope?) the procedure should more or less meet the conditions. As far as keyboard language goes, the procedure could be modified to choose the uppercase chars based on a languageID parameter passed, I guess for any really professional offering you'd probably have parsed that before the code ever got to this proc.

Posted: Fri Jul 28, 2006 4:21 am
by dracflamloc
It works except that delay cant be there. It would mess up the rest of the game.

Posted: Fri Jul 28, 2006 1:48 pm
by dracflamloc
i just removed the delay altogether. the repeating is pretty fast this way but its much better than the other one i had.