December 04, 2020, 11:25:37 AM

Author Topic: [bmx] Key input handling by Pineapple [ 1+ years ago ]  (Read 552 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bmx] Key input handling by Pineapple [ 1+ years ago ]
« on: June 29, 2017, 12:28:42 AM »
Title : Key input handling
Author : Pineapple
Posted : 1+ years ago

Description : Supports registering multiple keypresses at defined intervals while a key is held down. It can also decrease that interval based on how long the key has been held down. (Which imitates the behavior of a typical text field, though with a little more functionality.) Also supports requiring modifier keys being held down to register a given keypress.

Code :
Code: BlitzMax
  1. '       --+-----------------------------------------------------------------------------------------+--
  2. '         |   This code was originally written by Sophie Kirschner (sophiek@pineapplemachine.com)   |  
  3. '         | It is released as public domain. Please don't interpret that as liberty to claim credit |  
  4. '         |   that isn't yours, or to sell this code when it could otherwise be obtained for free   |  
  5. '         |                because that would be a really shitty thing of you to do.                |
  6. '       --+-----------------------------------------------------------------------------------------+--
  7.  
  8.  
  9. SuperStrict
  10.  
  11. Import brl.polledinput
  12. Import brl.linkedlist
  13.  
  14. ' Example program
  15.  
  16. Rem
  17.  
  18. ' Try pressing and holding shift and the spacebar down to see how stuff works; a pixel is added every time a press is registered.
  19.  
  20. Graphics 256,256
  21. Local space:key=createkey(key_space,key.shift,400,0.9)
  22. Local esc:key=createkey(key_escape)
  23. Local x%=0,y%=0
  24. Repeat
  25.         updatemodkeys
  26.         If space.get() Then
  27.                 Plot x,y
  28.                 x:+1
  29.                 If x>=GraphicsWidth() Then x=0;y:+1
  30.         EndIf
  31.         Flip
  32.         If esc.get() Then End
  33. Forever
  34.  
  35. EndRem
  36.  
  37.  
  38.  
  39. ' Backbone of the stuff.
  40. ' n                     -               the scancode. (for example, key_space)
  41. ' m                     -               the modifier. (for example, key.shift)
  42. ' d                     -               initial delay between presses in ms. (-1 means only register initial keypress.)
  43. ' delaymod              -               every time it registers a press while the key is held down, the time until the next press is registered is multiplied by this amount.
  44.  
  45. Function createkey:key(n%,m%=0,d%=-1,delaymod!=1)
  46.         Local k:key=New key
  47.         k.addkey n,m
  48.         k.keydelay=d
  49.         k.delaymod=delaymod
  50.         Return k
  51. End Function
  52.  
  53. ' Key input type
  54. Type Key
  55.         Field keys:TList=CreateList()
  56.         Field keydelay%=210,currentdelay%=-1,mindelay%=8
  57.         Field delaymod!=1
  58.        
  59.         Const none%=%000
  60.         Const any%=%1000
  61.         Const ctrl%=%100,shift%=%010,alt%=%001
  62.         Const ctrlshift%=%110,shiftctrl%=%110,ctrlalt%=%101,altctrl%=%101,shiftalt%=%011,altshift%=%011
  63.         Const ctrlaltshift%=%111,ctrlshiftalt%=%111,altshiftctrl%=%111,altctrlshift%=%111,shiftctrlalt%=%111,shiftaltctrl%=%111
  64.        
  65.         Method setmod(kind%)
  66.                 For Local k:control_key=EachIn keys
  67.                         k.modkind=kind
  68.                 Next
  69.         End Method
  70.         Function Create:Key(n0%=-1,mod0%=0,n1%=-1,mod1%=0,n2%=-1,mod2%=0,n3%=-1,mod3%=0)
  71.                 Local k:Key=New Key
  72.                 If n0>=0 k.AddKey n0,mod0
  73.                 If n1>=0 k.AddKey n1,mod1
  74.                 If n2>=0 k.AddKey n2,mod2
  75.                 If n3>=0 k.AddKey n3,mod3
  76.                 Return k
  77.         End Function
  78.         Method AddKey:control_key(v@,modkind%=0)
  79.                 Local n:control_key=control_key.Create(v,modkind)
  80.                 keys.addlast n
  81.                 Return n
  82.         End Method
  83.         Method RemoveKey%(n@,modkind%=-1)
  84.                 Local ret%=0
  85.                 For Local c:control_key=EachIn keys
  86.                         If c.num=n And (c.modkind=modkind Or modkind=-1) Then keys.remove c;ret=1
  87.                 Next
  88.                 Return ret
  89.         End Method
  90.         Method get%()
  91.                 Local resetdelay%=1
  92.                 Local isget%=0
  93.                 For Local k:control_key=EachIn keys
  94.                         If (Not isget) And k.get(currentdelay)
  95.                                 isget=1
  96.                         EndIf
  97.                         If resetdelay And k.down() Then
  98.                                 resetdelay=0
  99.                         EndIf
  100.                         If isget And (Not resetdelay) Then Exit
  101.                 Next
  102.                 If resetdelay
  103.                         currentdelay=keydelay
  104.                 ElseIf keydelay<>-1
  105.                         currentdelay=Max(mindelay,currentdelay*delaymod)
  106.                 EndIf
  107.                 Return isget
  108.         End Method
  109.         Method down%()
  110.                 For Local k:control_key=EachIn keys
  111.                         If k.down() Return 1
  112.                 Next
  113.                 Return 0
  114.         End Method
  115.         Method downtime%()
  116.                 Local ret%=0,now%=MilliSecs()
  117.                 For Local k:control_key=EachIn keys
  118.                         If k.down() Then ret=Max(ret,now-k.lastms)
  119.                 Next
  120.                 Return ret
  121.         End Method
  122.         Method flush()
  123.                 For Local k:control_key=EachIn keys
  124.                         k.flush
  125.                 Next
  126.         End Method
  127. End Type
  128.  
  129. ' A key object can actually have several literal keys attached to it, and will register a press if any of the associated keys are pressed. This is the object that actually keeps track of presses.
  130. Type control_key
  131.         Field num@,lastms%,init%=1
  132.         Field modkind%=0
  133.        
  134.         Method flush()
  135.                 lastms=MilliSecs()
  136.         End Method
  137.         Function Create:control_key(n@,modkind%=0)
  138.                 Local c:control_key=New control_key
  139.                 c.num=n;c.modkind=modkind
  140.                 Return c
  141.         End Function
  142.         Method get%(keydelay%)
  143.                 If KeyDown(num) And ((modkind=modkeys) Or (modkind=key.any)) 'ismod
  144.                         If MilliSecs()-lastms=>keydelay And keydelay>=0 lastms=MilliSecs();Return 1
  145.                         If init init=0;Return 1
  146.                 Else
  147.                         init=1;lastms=MilliSecs()
  148.                 EndIf
  149.                 Return 0
  150.         End Method
  151.         Method down%()
  152.                 Return KeyDown(num)
  153.         End Method
  154. End Type
  155.  
  156. ' This stuff is for keeping track of modifier keys.
  157. Global modkeys%=0
  158. Function _keys_ctrl%()
  159.         Return KeyDown(key_lcontrol) | KeyDown(key_rcontrol)
  160. End Function
  161. Function _keys_shift%()
  162.         Return KeyDown(key_lshift) | KeyDown(key_rshift)
  163. End Function
  164. Function _keys_alt%()
  165.         Return KeyDown(key_lalt) | KeyDown(key_ralt)
  166. End Function
  167.  
  168. ' You should run this function once every frame if modifier keys matter.
  169. Function updatemodkeys()
  170.         modkeys=(_keys_ctrl() Shl 2)|(_keys_shift() Shl 1)|(_keys_alt())
  171. End Function


Comments : none...

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal