Hi :) how know when a keyboard key is just being released

Blitz3D Forums/Blitz3D Programming/Hi :) how know when a keyboard key is just being released

Filax(Posted 2004) [#1]
Have an idea ?


GitTech(Posted 2004) [#2]
Check the time, between now, and the last time the key was down?


Filax(Posted 2004) [#3]
good idea ! have you a piece of code ?


Shambler(Posted 2004) [#4]

sKey57Down=False

While Not KeyHit(1)

If KeyDown(57) Then sKey57Down=True ; Can also use KeyHit(57)

If (Not KeyDown(57)) And sKey57Down=True
	Print "key 57 was just released!"
	sKey57Down=False
EndIf


Wend




WolRon(Posted 2004) [#5]
kuFlag = True

;beginning of loop
  kdFlag = KeyDown(?)
  If kdFlag = False and kuFlag = False
    ;do something here
  EndIf
  If kdFlag = True
    kuFlag = False
  Else
    kuFlag = True
  EndIf
;end of loop


or

kdFlag=False

;beginning of loop
  If KeyDown(?)
     kdFlag=True
  Else
    If kdFlag=True
      ;do something here
      kdFlag=False
    EndIf
  EndIf
;end of loop



semar(Posted 2004) [#6]
Or use a bidimensional array which stores the status of each key you need.

Suppose you want to chek for the key code 57, 15 and 21 (57 should be space bar, I don't recall now, the rest are examples but you should get the drift).

That are 3 keys to be tested, right ? So we can use a bidimensional array of three elements:
dim ak(3,2)


the first value is the keycode, the second is the status.

So, at the beginning we can set up the array:
ak(1,1) = 57 ;the key code
ak(1,2) = 0 ;status: depressed

ak(2,1) = 15 ;the key code
ak(2,2) = 0 ;status: depressed

ak(3,1) = 21 ;the key code
ak(3,2) = 0 ;status: depressed




Note that I ignore the ak(0) element here, you can optimize it if you like.

Now, we can test for the key pressed and depressed:

for n = 1 to 3 ;where 3 is the total number of keys to be tested
if keydown(ak(n,1)) then ;if key is pressed then

;check if it the key has been pressed right now
if ak(n,2) = 0 then ;the status was: depressed
   ;<----------------------------- KEY PRESSED !
endif
ak(n,2) = 1 ;set the status to 'pressed'

else ;the key is not pressed

;check if the key has been depressed right now
if ak(n,2) = 1 then
   ;<----------------------------- KEY RELEASED !
endif

ak(n,2) = 0 ;set the status to depressed
endif
next


Hope this has sense for you,
Sergio.


Filax(Posted 2004) [#7]
Thx !


Filax(Posted 2004) [#8]
An idea for put in function ?

i have truy

Global kuFlag = True


While Not KeyHit(1)

If KeyUp(200) Then
Print "HUUUP"

EndIf

If KeyUp(57) Then
Print "HUUUP"

EndIf


Wend

Function KeyUp(Key)
kdFlag = KeyDown(Key )
If kdFlag = False And kuFlag = False
good=True
EndIf
If kdFlag = True
kuFlag = False
Else
kuFlag = True
EndIf

If Good=True Then
Return Good
EndIf
End Function


but don't work ;(


WolRon(Posted 2004) [#9]
Does this work better?
Function KeyUp(Key) 
  kdFlag = KeyDown(Key ) 
  If kdFlag = False And kuFlag = False
    kuFlag = True
    Return True
  EndIf 
  If kdFlag = True 
    kuFlag = False 
  Else 
    kuFlag = True 
  EndIf 
  
  Return False
End Function 



fredborg(Posted 2004) [#10]
Voila!
Global keybuf[255]

Repeat
	MyUpdateKeyBuffer()

	; Press 1
	If MyKeyHit(2)
		DebugLog "Key 1 pressed at "+MilliSecs()
	End If
	
	; Release 1
	If MyKeyUp(2)
		DebugLog "Key 1 released at "+MilliSecs()
	End If

Until MyKeyHit(1)


Function MyKeyHit(i)
	If keybuf[i] = 1 Then Return True
End Function

Function MyKeyDown(i)
	If (keybuf[i] > 0) And (keybuf[i] < 3) Then Return True
End Function

Function MyKeyUp(i)
	If keybuf[i] = 3 Then Return True
End Function

Function MyUpdateKeyBuffer()
	
	For i = 1 To 255
		Select keybuf[i]
			Case 0: ; Nothing
				If KeyDown(i) Or KeyHit(i)
					keybuf[i] = 1
				End If
			Case 1: ; Key was hit in last update
				If KeyDown(i)
					keybuf[i] = 2
				Else
					keybuf[i] = 3
				End If
			Case 2: ; Key was held down in last update
				If KeyDown(i) = False
					keybuf[i] = 3
				End If
			Case 3: ; Key was released in last update
				keybuf[i] = 0
		End Select
	Next
	
End Function



Filax(Posted 2004) [#11]
No ?? strange ! but i have find another solution by type :

Type TKeyUp
Field Key
Field Flag=True
End Type





Up=initkey(200)
down=initkey(208)

While Not KeyHit(1)

If KeyUp(Up) Then
Print "HUUUP"
EndIf

If KeyUp(Down) Then
Print "HUUUP"
EndIf


Wend

Function initkey(key)
K.TKeyUp=New TKeyUp
K\Key=Key
K\Flag=True
Return Handle(K)
End Function


Function KeyUp(Id)
K.TKeyUp=Object.TKeyUp(Id)
kdFlag = KeyDown(K\Key )
If kdFlag = False And k\Flag = False
good=True
EndIf
If kdFlag = True
k\Flag = False
Else
k\Flag = True
EndIf

If Good=True Then
Return Good
EndIf
End Function


WolRon(Posted 2004) [#12]
Oh, I see, you were using the same flag for more than one key. Yeah, you have to use types, or arrays, or seperate variables for each key.


AbbaRue(Posted 2004) [#13]
I know in assembly language that when a key is pressed it returns a scan code and when it is released it returns a different scan code.
That is how the system knows how long a key is held down.
I used this in my code to prevent multiple enteries of the same key. I only checked for the key release scan code for each key, so the code didn't respond until you released the key.
I don't think Blitz is taking advantage of this feature yet. But maybe someone will write a library for blitz that does.


Curtastic(Posted 2004) [#14]
fredborg:
try putting 'delay 400' at the end of the loop. it either wont catch the key or will always think its down.

shambler, wolron, semar:
suppose the key is pressed and quickly released while some other part of the programis being executed.


I have a solution. I will post it


Curtastic(Posted 2004) [#15]
this seems to always work
the delays are to show that even if other parts of the program are taking a long time, one keydown/keyup will always be caught each loop.

Dim hit(256),olddown(256),down(256),up(256)

Print "begin"

Repeat
	updatekeys()

	Delay 300

	If hit(57) Then Print "hit"
	If up(57) Then Print "let go"
	If KeyHit(1) Then End

	Delay 300
Forever


Function updatekeys()
	Local i
	
	For i=1 To 256
		hit(i)=KeyHit(i)>0
		down(i)=KeyDown(i)
		If hit(i) And olddown(i) Then
			up(i)=1
		Else
			If hit(i) Then olddown(i)=1
			up(i)=(olddown(i)=1 And down(i)=0)
			If up(i) Then olddown(i)=0
		EndIf
	Next
End Function



Filax(Posted 2004) [#16]
Thanks for your help !


fredborg(Posted 2004) [#17]
Coorae: Changed mine too :)


darklordz(Posted 2004) [#18]
@Fredborg > thanks for the code man.... I didn't ask for it but it helps.... Now all my menu actions take place upon release :P