flushkeys bug

Archives Forums/BlitzPlus Bug Reports/flushkeys bug

meemoe_uk(Posted 2013) [#1]
Graphics 640,480

key_esc=1
key_1=2

While Not KeyDown(key_esc)
If KeyDown(key_1) Then Print "hello!"
FlushKeys()
Wend

***

when the 1 key is pressed down continuously :
in blitz 2D the result is a recurring output of "hello!"
in blitzplus v1.47 , the result is a single "hello!".

Seems flushkeys is bugged in blitzplus. In addition to flushing the keydown , it also hits a switch so that a keydown is ignored until a keyhit event occurs.

The blitz 2D is the correct and expected result.

When I port my blitz 2D games over to blitzPlus I find that the user loses smooth control and has to tap controls to reactivate the (dead!) keyboard after a flushkeys command.


---

Oh er, where is everyone? I've only just moved from blitz 2d to blitzPlus.
If mark doesn't touch blitzplus these days, anyone know any simple workarounds?


Yasha(Posted 2013) [#2]
....The BlitzPlus behaviour looks exactly like the correct and expected result to me. That sounds more like a bug in Blitz2D.

I don't see why you would want to combine KeyDown with FlushKeys anyway. FlushKeys is for clearing a backlog of events that happened in the past; KeyDown is for events happening right now. The two serve different purposes.


meemoe_uk(Posted 2013) [#3]
>I don't see why you would want to combine KeyDown with FlushKeys anyway.

To flush any backlog of input before the game starts. But the user should be able to hold down keys as the games starts and have the game react to those keys in the 1st loop of the game. Instead, with this blitzplus bug, the user has to wait till after the game started, then press the key. Otherwise, after a flushkeys, any key the user is holding down in anticipation of the game starting is ignored by blitzplus until a keyhit event takes place.

Every action game I've ever played I can think of the user can hold down inputs as the game starts and game will react to them.

This is all pants anyway. Looks to me Sibly has zero to do with blitzplus these days, the only reason the B+ forum is still here is for posterity. I can implement a botch to cover the B+ flushkeys fail.


Yasha(Posted 2013) [#4]
If you want it to handle things that transpired before the game began, why is it in the main loop? Run it once before the main loop. There's no reason to be repeating it every frame after its work is done.

This is not a bug in BlitzPlus. Unless there's a reason why it should run every frame, this is a design error in your program. FlushKeys is working as designed and getting rid of the key press event (there is no "key being held down" event in Windows; keys go down and they go up and send a message for each. The system you're imagining doesn't exist).

If you need complicated keyboard interaction, it may be easier to roll your own input event layer on top of the builtins, running once at the start of the main loop and providing "soft" status updates for your application code to check, rather than distributing Key* calls throughout the code.


meemoe_uk(Posted 2013) [#5]
If you want it to handle things that transpired before the game began, why is it in the main loop?
Because besides the core game, my programs often include title screen with menus, text editor, controls editor, level editor, a player can die and restart the level. Some of these features have been seen computer games for over 40 years.

This is not a bug in BlitzPlus
Yes it is. I say so. I'm a blitzplus user. I have a say it what are bugs.
Specifically its useful feature of blitz2D that was removed in blitzplus.

Unless there's a reason why it should run every frame, this is a design error in your program.
You've randomly picked up this 'every frame' meme out your imagination and you are running with it. None of my games have a flushkeys every frame.

>there is no "key being held down" event in Windows
So there's no reason to shut down the blitz flag 'keydown'. Why randomly remove the keydown functionality of blitz until reactivation by a keyhit event?

The system you're imagining doesn't exist
Wrong. Check blitz2D. It existed there. Your idea that blitz shouldn't have any functionality that windows doesn't already provide is a bit dumb. If we only wanted windows functions no one would buy blitz.

If you need complicated keyboard interaction, it may be easier to roll your own input event layer on top of the builtins

Needing flushkeys to not disable keydown until next keyhit is hardly 'complicated keyboard interaction'. And as I said already, I've already written some botch code to cover this blitzplus fail.

***

* user presses key *
flushkeys
* user still holding key down *
keydown(key)
* blitzplus returns 0 * , * blit2D returns 1 *

the key is being held down, so blitzPlus is wrong, blitz 2D is right.


Yasha(Posted 2013) [#6]
OK, firstly and most importantly:

Yes it is. I say so. I'm a blitzplus user. I have a say it what are bugs.


No you don't. Bugs are objective. Just because you don't understand the command does not make its behaviour buggy. Your program is improperly designed, and relying on what is more likely a bug in Blitz2D that has been corrected. If you say you want 1 + 1 to equal 3 because it would make your level loader work better, that doesn't make the result 2 buggy. FlushKeys is working as designed and documented. There is no fail here.


Why randomly remove the keydown functionality of blitz until reactivation by a keyhit event?


Because you have specifically requested it be removed by calling the function that requests the flag be removed. This is what the function does. Again, this is like assigning a value to a variable then being surprised that it changed. If you don't want this to happen, stop ordering it to happen.


randomly picked up this 'every frame' meme out your imagination


The only reason this is a problem in your posted example in the OP is because FlushKeys is in the loop body instead of before the loop body, when you have said that you want to flush events only that took place before the loop body. If you have more than one loop or rendering system in your project, whatever; you've described a situation where you only want events flushed at particular times, and are describing your solution as flushing events all the time, for some reason. Place FlushKeys before several loops or within conditionals or whatever as suits your program's actual structure, but the point is that your code as posted contains an obvious logical error, which is that you're issuing far more flush commands than you need and at times when they aren't wanted. You can completely solve the problem by fixing this logical error without needing to rely on a broken FlushKeys implementation.

Besides which there is a logical disconnect both in what you're writing and what you appear to want. In code: there is no reason to use FlushKeys with KeyDown at any time. They are not designed to work together anyway; one prepares for input and the other directly handles input. One is a setup command, one is a realtime command. There is no functionality overlap (KeyDown shouldn't be affected by what happened before the keypress anyway, so there is no need for a flush for it to work correctly; if there is, you're mixing multiple input methods, which never works). In what you want: for the user to have their relevant keystrokes recognised while deleting their irrelevant ones. This is logically incoherent.


blitz shouldn't have any functionality that windows doesn't already provide is a bit dumb


My idea is that functions should behave as they're documented and intended. Absolutely nowhere does the documentation say that KeyDown generates a whole bunch of extra events and is therefore immune to event-flushing, and to implement this would require more code in the hidden layer than to not do it this way and assume extra behaviour that has not been suggested to exist. Therefore it makes no sense to assume that FlushKeys would not affect KeyDown. If you want this behaviour, use a single-point-of-input system and add it directly.


GaryV(Posted 2013) [#7]
Yasha: Quit feeding the troll!


meemoe_uk(Posted 2013) [#8]
You aren't helping.

And my kid detectors are flashing red. Dogged defence of something from which you've got nothing to gain from means you just like arguing for the sake of it. I'm not buying any of your BS.

In code: there is no reason to use FlushKeys with KeyDown at any time.
Yes there is.
If flushkeys isn't used then the in game user controlled character are liable to act on prior-to-game keyhit inputs, typically fire buttons. So flushkeys is necessary to get rid of fire button input. But players often like to hold down inputs as the game starts, this depends on keydown to not be deactivated with flushkeys.

And since I'm fiddling with keydown at the mo I checked to see if flushkeys effects other windows programs. It doesn't. So when you say...
FlushKeys is working as designed and getting rid of the key press event (there is no "key being held down" event in Windows; keys go down and they go up and send a message for each.
Your wrong. Windows can detect keydown held down before, thru, and after flushkeys is executed in blitz.
So can blitz2d. BlitzPlus can't. It's a bug.


I can't hang around correcting the elementary mistakes in your cooked up waffle all day. I've bin coding for 20+ years and I can spot a charlatan, even if they pack their signature with techy links. Later kid.


Kryzon(Posted 2013) [#9]
Hi. I think there's some confusion on what is the expected behavior of FlushKeys().
FlushKeys() can only affect the behavior of KeyDown() calls that come after it and that query the state of a key that was pressed down on the keyboard before FlushKeys() was called.

When BlitzPlus polls the system for events, it uses the key-up and key-down events that your application received to mark a key as pressed down or released.
These events are "fire-once"; They come once per change of key state. So BlitzPlus knows a key is pressed when it receives a key-down event for it, and it will consider this key being pressed down all the time until it receives a key-up event for this key, indicating that it was released.

When you call FlushKeys(), BlitzPlus clears its own internal state variables for all keys. Subsequent calls to KeyDown() for the same key will all query its state variable, and these calls will yield 'False' even if the key is still being pressed on the keyboard. Your application only received a single message of key-down, and it was disregarded by BlitzPlus the moment you called FlushKeys().

KeyHit(), on the other hand, queries and then resets a different variable, one that stores the number of times a key was hit since the last call of KeyHit() to it. It does not consider the key's state, so it's not influenced by FlushKeys() at all.
If KeyHit() influences FlushKeys()+KeyDown() behavior in any way in Blitz2D, it's most likely because it uses an asynchronous or at least different input scheme than that of BlitzPlus\Blitz3D\BlitzMax.

- - - - -
If you want your program to enable the user to have immediate control as soon as the gameplay starts, then as soon as the user hits the PLAY button (or whatever button that immediately precedes gameplay), don't call a FlushKeys() or any keys that were pressed before it will be ignored.
This is so for any Blitz product.


GaryV(Posted 2013) [#10]
or at least different input scheme than that of BlitzPlus\Blitz3D\BlitzMax.

It is also worth pointing out that Blitz2D used DirectInput where BlitzPlus\BlitzMax\Blitz3D all use WM_INPUT.


A22(Posted 2013) [#11]
I made a small example program to demonstrate this.

If one wants to clear all unnecessary key presses when the game starts (such as fire button presses), but also wants to give the Player immediate control, then there is a method to achieve this without the flushkeys command.

Here:

Graphics 1024,768,0,2

SetBuffer BackBuffer()

key_esc=1
key_1=2
key_S=31
key_SPACE=57

looptime=CreateTimer(50)



.GameMenu
;----------------------------------------------
Text 300,100,"MAIN MENU - Press 'S' to start game"
Flip


;###########################
Repeat



; Flushkeys Method
; This method loses all keys that have been pressed or are being held down

;------------------------
;If KeyHit(key_S)=1 Then

;FlushKeys
;Goto MainLoop

;End If
;------------------------



; LOL Method
; This method does not, only "LOL=0" key presses are lost
; the LOL=0 command actually does nothing
; we just check the key once to remove old key presses from memory

;------------------------
If KeyHit(key_S)=1 Then

If KeyHit(key_SPACE)=1 Then LOL=0
Goto MainLoop

End If
;------------------------



WaitTimer looptime

Forever
;###########################


;----------------------------------------------





.MainLoop
;----------------------------------------------
While Not KeyDown(key_esc)


Cls

Color 255,255,255
Text 300,120,"Hold down '1' to print 'HELLO!'"
Text 300,140,"Press 'Space' to print 'SPACE!'"
Text 300,160,"Press 'ESC' to exit"

If KeyDown(key_1)=1 Then Color 255,255,0 : Text Rnd(500),Rnd(500),"HELLO!"
If KeyHit(key_SPACE)=1 Then Color 255,0,0 : Text Rnd(500),Rnd(500),"SPACE!"


WaitTimer looptime
Flip


Wend
;----------------------------------------------



End



In this example we first have a "Start Screen", where the user must press "S" to start the game. This takes you to the "Game Screen", where the controls are:
"1" to print 'hello' and "Space" to print 'space'.

But when the game starts we "empty" the Space bar presses by checking it once, with that LOL=0 statement, which actually does nothing, expect that it causes the Space bar presses to disappear from memory.

This can be used as a workaround, and flushkeys is not needed at all.

But in comparison the code includes the flushkeys method as well, but I commented it out, but you can reactivate it to see the difference between these two methods. :)

I learned this LOL=0 trick when I once had similar troubles with the "Flushjoy" command.