Better MouseHit KeyHit Commands

BlitzMax Forums/BlitzMax Programming/Better MouseHit KeyHit Commands

Kippykip(Posted 2013) [#1]
Made these because the originals were buggy unless you use flushkeys but that flushes KeyDown as well (Except in Blitz3D/BlitzPlus)

So I wrote these enjoy!

Global xKeyArray:Int[]
xKeyArray = New Int[255]
Global xMouseArray:Int[]
xMouseArray = New Int[8]

Function xKeyHit(key)
	If(KeyDown(key))
		If(xKeyArray[key])
			xKeyArray[key] = False
			Return True
		EndIf
	EndIf
	If Not(KeyDown(key))
		xKeyArray[key] = True
	EndIf
EndFunction

Function xMouseHit(key)
	If(MouseDown(key))
		If(xMouseArray[key])
			xMouseArray[key] = False
			Return True
		EndIf
	EndIf
	If Not(MouseDown(key))
		xMouseArray[key] = True
	EndIf
EndFunction



GfK(Posted 2013) [#2]
Made these because the originals were buggy
The 'originals' aren't buggy at all. You're probably not doing it right.


Brucey(Posted 2013) [#3]
And your code doesn't appear to have any bugs in it either!

For example, what happens if you push down and release a key between calls to your xKeyHit() function ? How do you know if you've pressed a key during that time?


Kryzon(Posted 2013) [#4]
Hello.
I have to agree that the original Polled Input module is perfectly functional according to what it should do based on the documentation. It also replicates the Blitz3D behaviour.

What sort of bugs have you found?


Kippykip(Posted 2013) [#5]
The bugs I found were for example
I had in my blitz3d project that if you click in a zone it does something
but the problem I got was if I click anywhere outside the zone and as SOON as I hover the click zone WITHOUT CLICKING it would act like I clicked
But this was fixed by adding flushkeys/flushmouse to the loop

When I started porting it to blitzmax the "act like I clicked" thing still occurred but I also noticed flushkeys also resets keydown and mousedown so I couldn't move with wasd like on the blitz3d version cause it kept changing the keydown to false
So I deleted the line for flushkeys and made my own function and posted it here

Example 2: I press 2 to change the weapon from the fist to the pistol only when your ingame, when i'm on the mainmenu/pause and press 2, then press enter on new game (or esc to go back to the game), it changes to the pistol as soon as inGame = true

So in a way, this is keyHit without the need of flushkeys

For example, what happens if you push down and release a key between calls to your xKeyHit() function ? How do you know if you've pressed a key during that time?


Thanks for letting me know bruce
But I don't think I'll need to have a keyDown(KEY_1) with a keyHit(KEY_1) underneath c:


Brucey(Posted 2013) [#6]
Adding a FlushKeys call when you restart the game after being in a menu seems a natural/normal thing to do. In which case, there's no need to create a faulty version of KeyHit to replace the one that already works as designed.


GfK(Posted 2013) [#7]
Adding a FlushKeys call when you restart the game after being in a menu seems a natural/normal thing to do.
It's normal practice for me. If the player presses a bunch of keys during loading, all those presses get cached and processed when loading is complete. The only way around that is to flush the lot (keys AND mouse) immediately after any period of loading. You don't get any odd side-effects that way.

As for using MouseHit, I have a simple class that handles this. Every update, the value of each mouse button is put into a variable. I can check against that variable multiple times, whereas doing it directly with MouseHit would only work the first time. Again, this is perfectly normal behaviour.

Your not understanding how something works, doesn't mean it's broken.


TomToad(Posted 2013) [#8]
The bugs I found were for example
I had in my blitz3d project that if you click in a zone it does something
but the problem I got was if I click anywhere outside the zone and as SOON as I hover the click zone WITHOUT CLICKING it would act like I clicked
But this was fixed by adding flushkeys/flushmouse to the loop


Sounds like you are doing something like this
'Pseudocode
If MouseInZone()
   If MouseHit()
      DoSomething()
   End If
End If


Problem with that is the mouse hits are stored until you call MouseHit() or FlushMouse(). So basically you are saying if the mouse enters the zone, then check if the mouse button has ever been pressed. It would be better to check for mouse buttons first, then see what zone it is in once it is pressed. So something like this

'Pseudocode
If MouseHit()
   If MouseInZone()
      DoSomething()
   End If
End If


Now no need to call FlushMouse() as it is flushed every loop and will only call DoSomething() when in a zone.

ETA: Doing something like If MouseInZone() And MouseHit() Then DoSomething() is the same situation. MouseHit() is never called, and therefore never flushed if MouseInZone() is false. Switch the two around to fix that problem. If MouseHit() And MouseInZone() Then DoSomething()


Kippykip(Posted 2013) [#9]

Brucey
Adding a FlushKeys call when you restart the game after being in a menu seems a natural/normal thing to do. In which case, there's no need to create a faulty version of KeyHit to replace the one that already works as designed.
-
Kippykip
Made these because the originals were buggy unless you use flushkeys but that flushes KeyDown as well (Except in Blitz3D/BlitzPlus)


The problem is with blitzmax is that Flushkeys also resets keydown unlike blitz3d/plus where it just resets keyhit only

I don't want the player to stop whenever I press a weapon button
The code I created that is *faulty* doesn't do that cache problem so I don't even need to use flushkeys at all!
unless there's a flushkeys that only flushes keyhit i'm sticking with mine

Not sure why people are saying that mine is very unstable, can you be more specific?


GfK(Posted 2013) [#10]
Not sure why people are saying that mine is very unstable, can you be more specific?
I never said it was unstable. I said that you've attempted to solve a problem that never existed in the first place.


Kippykip(Posted 2013) [#11]
GfK
Not sure why people are saying that mine is very unstable, can you be more specific?
I never said it was unstable. I said that you've attempted to solve a problem that never existed in the first place.

Bruce said it was unstable, anyway yes the only reason I made this is because the new flushkeys also flushes keydown which ruined movement in the game
I'll correct my first post, keyhit itself isn't buggy (At the time I thought because I only just moved from blitz3d to minib3d)
But because flushkeys was changed I thought it was buggy, my bad

So when I was making xKeyHit, I noticed it didn't do that cache thing like regular keyHit does so didn't need to make my own xFlushKeys
So yeah


TomToad(Posted 2013) [#12]
You'll probably find that there is more than one way to do things, and if your code works for you, then that's great. However, sometimes it is easy to create convoluted code to accomplish something when there is a much simpler solution.

Check out the two examples below. move the dot around with WASD, and "jump" with the spacebar. When you "jump" on the green square, a counter increases. Notice in the first example, you can jump somewhere off the square, then your count suddenly increases the moment you enter the square. Probably not the intended behavior.

This is the result of how BlitzMAX evaluates conditional clauses. When you And several clauses together, BM stops evaluating after the first false is returned. That means when you're outside the rectangle, KeyHit() never gets called and the spacebar key never gets reset, so the moment you enter the rectange, KeyHit() gets called for the very first time and will return True.

The second example is almost identical, except that KeyHit() is checked before checking if the player is within the rectangle. That means that the key will be reset every loop, leaving all other keys alone, no need for FlushKeys(). Now the program behaves the way you'd expect.

First example:

Second Example:


Of course, it gets a little more complicated if you want to do one thing while in the rectangle while a key is pressed and do something else when no key is pressed. Then I'd recommend storing the result of the KeyHit() in a flag each loop.


Kippykip(Posted 2013) [#13]
Nice example Tom!


Calibrator(Posted 2013) [#14]
> As for using MouseHit, I have a simple class that handles this. Every update, the value of each mouse button is put into a variable. I can check against that variable multiple times, whereas doing it directly with MouseHit would only work the first time. Again, this is perfectly normal behaviour.

Exactly.

I see no advantage in using repeated MouseHit() or KeyDown() calls instead (except in small demo programs, of course).


Kippykip(Posted 2013) [#15]
Well's a massive issue in the map creator, but in the game it's a small issue when wanting to change weapons


Derron(Posted 2013) [#16]
Another thing is receiving hits to special chars (euro sign etc) is easier done in an wrapper - especially as it needs ?linux and ?win32 flags as keycodes differ.


bye
Ron