QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: johannhowitzer on July 11, 2019, 02:44:13 am

Title: Odd multiple input problem
Post by: johannhowitzer on July 11, 2019, 02:44:13 am
Hey all.  I'm working on a prototype for a shooter, and it has aimable shooting.  Here's the code block that handles inputs.

Code: QB64: [Select]
  1.    throw.x = 0
  2.    if _keydown(cvi(arrow(left))) = true then throw.x = -1
  3.    if _keydown(cvi(arrow(right))) = true then throw.x = 1
  4.    throw.y = 0
  5.    if _keydown(cvi(arrow(up))) = true then throw.y = -1
  6.    if _keydown(cvi(arrow(down))) = true then throw.y = 1
  7.    if throw.x = 0 and throw.y = 0 then throw.x = 1
  8.  
  9.    if _keydown(asc(" ")) = true and spacepress = false then
  10.       spacepress = true
  11.       call spawn_shot(0, throw.x, throw.y)
  12.    end if
  13.  
  14.    if _keydown(asc(" ")) = false and spacepress = true then spacepress = false

arrow() just contains the ASCII arrow key data.  The arrow key section acts like a joystick and respects held inputs to aim 8-way, with "neutral" position resulting in aiming to the right by default (sidescroller like Gradius).  I have an aiming indicator and this is behaving properly.

What's unusual is that this IS working for shooting in all of the 8-way input directions... except up-left.  It will aim that way, but the spacebar isn't causing a shot to spawn.  There is shot to ship collision, but every shot carries the index of the ship that created it - that's what the first parameter "0" is in spawn_shot, and the collision routine ignores matching ships and shots to avoid friendly fire, so the shot isn't immediately hitting the player's ship here.

EDIT: This is really weird.  Further bug testing showed that only certain combinations of three keys do not play nice with _keydown.  Specifically, it doesn't like up, left, and space together.  When I held left, then added holding space, then pressed up, the aiming indicator did not move to aiming up-left.
Title: Re: Odd multiple input problem
Post by: FellippeHeitor on July 11, 2019, 06:07:51 am
You’ve found your keyboard’s hardware limitation to detect multiple keys down at once. https://en.wikipedia.org/wiki/Rollover_(key) (https://en.wikipedia.org/wiki/Rollover_(key))

You’re likely to get different results across different systems you’ll test your game in.
Title: Re: Odd multiple input problem
Post by: FellippeHeitor on July 11, 2019, 07:45:38 am
Try this:
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(400, 400, 32)
  2.  
  3.  
  4. midx = _WIDTH / 2
  5. midy = _HEIGHT / 2
  6.  
  7.     xdir = 0
  8.     ydir = 0
  9.  
  10.     IF _KEYDOWN(18432) THEN ydir = ydir - 1
  11.     IF _KEYDOWN(20480) THEN ydir = ydir + 1
  12.     IF _KEYDOWN(19200) THEN xdir = xdir - 1
  13.     IF _KEYDOWN(19712) THEN xdir = xdir + 1
  14.  
  15.     shooting = _KEYDOWN(32)
  16.     IF shooting THEN col = _RGB32(255, 0, 0) ELSE col = _RGB32(255)
  17.  
  18.     CLS
  19.     COLOR col
  20.     PSET (midx, midy)
  21.     DRAW "D " + STR$(150 * ydir) + "R " + STR$(150 * xdir)
  22.     _DISPLAY
  23.     _LIMIT 30

On my machine I can go all directions and still shoot with space. What results do you get with the snippet above?
Title: Re: Odd multiple input problem
Post by: johannhowitzer on July 11, 2019, 08:36:32 am
With your code, the lines turned red in every direction but up-left.  "Key jamming and ghosting" section of that Wikipedia article seems relevant to my situation.  Necessary to use the arrow keys here, but I bet keys other than spacebar will work well for "fire."  Z has already worked - this is a common choice among some PC release shooter games, such as Touhou.

While QB64 won't be my final language for the project and I'm just doing proof of concept stuff right now, this is a hardware issue and I'll need to go searching for more complete info about keyboard jamming so this won't be an issue for people in the final version.

Thanks for your help!
Title: Re: Odd multiple input problem
Post by: TempodiBasic on July 11, 2019, 12:35:55 pm
Hi johannhowitzer

about
Quote
arrow() just contains the ASCII arrow key data.
look here what it happens to use a string data and convert it into integer with CVI function
Code: QB64: [Select]
  1. CONST left = 1, right = 2, up = 3, down = 4, true = -1
  2. DIM arrow(1 TO 10) AS STRING
  3. arrow(left) = "19200"
  4. arrow(right) = "19712"
  5. arrow(up) = "18432"
  6. arrow(down) = "20480"
  7. COLOR 11, 2
  8. PRINT CVI(arrow(left)), CVI(arrow(right)), CVI(arrow(up)), CVI(arrow(down))
  9. PRINT (arrow(left)), (arrow(right)), (arrow(up)), (arrow(down))
this experience comes out trying to emulate your error with _keydown input
but using an array of integer I have no problem
see here
Code: QB64: [Select]
  1. CONST left = 1, right = 2, up = 3, down = 4, true = -1
  2. DIM arrow(1 TO 10) AS INTEGER
  3. arrow(left) = 19200
  4. arrow(right) = 19712
  5. arrow(up) = 18432
  6. arrow(down) = 20480
  7. COLOR 11, 2
  8.  
  9. PRINT (arrow(left)), (arrow(right)), (arrow(up)), (arrow(down))
  10.     CLS
  11.     throw.x = 0
  12.     LOCATE 3, 1: PRINT "Xmove=";
  13.     IF _KEYDOWN((arrow(left))) = true THEN throw.x = -1: PRINT " Left   "
  14.     IF _KEYDOWN((arrow(right))) = true THEN throw.x = 1: PRINT " Right "
  15.     throw.y = 0
  16.     LOCATE 5, 1: PRINT "Ymove=";
  17.     IF _KEYDOWN((arrow(up))) = true THEN throw.y = -1: PRINT " UP    "
  18.     IF _KEYDOWN((arrow(down))) = true THEN throw.y = 1: PRINT " Down "
  19.     IF throw.x = 0 AND throw.y = 0 THEN throw.x = 1
  20.  
  21.     IF _KEYDOWN(32) = true AND spacepress = false THEN
  22.         spacepress = true
  23.         LOCATE 1, 1: PRINT "Spacepress="; spacepress; "  "
  24.         '     CALL spawn_shot(0, throw.x, throw.y)
  25.     END IF
  26.     IF _KEYDOWN(27) THEN END
  27.     IF _KEYDOWN(32) = false AND spacepress = true THEN spacepress = false
  28.     LOCATE 1, 1: PRINT "Spacepress="; spacepress; "   "
  29.     _LIMIT 10
Title: Re: Odd multiple input problem
Post by: johannhowitzer on July 11, 2019, 02:41:50 pm
Thanks, but I ran your program and it had the same issue as before on my laptop - it's a hardware thing.  It's not something you can code out, as everyone's hardware is different; it's something you have to design your inputs around.  Presumably it's why many PC shooters use Z for fire, perhaps the hardware conflict doesn't exist or isn't as common between arrow keys and Z.

As an aside, the arrow() array doesn't contain the numbers in string format, it contains the following, a throwback to my QBasic days.

Code: QB64: [Select]
  1. dim arrow(4) as string * 2
  2. arrow(up) = chr$(0) + chr$(72)
  3. arrow(right) = chr$(0) + chr$(77)
  4. arrow(down) = chr$(0) + chr$(80)
  5. arrow(left) = chr$(0) + chr$(75)
  6.  
Title: Re: Odd multiple input problem
Post by: TempodiBasic on July 11, 2019, 03:49:11 pm
Hi  johannhowitzer

sorry but I don't agree more about hardware issue, I think that it is about  code... (also because when I see some terrific combo used in some games I think of a player of piano and not a gamer)

make this experience with me

please run the original your code with your array initialization...
well with my printing results modification you cannot get these combo keys

1. holding spacebar (32 keycode)  AND
   1.2 holding Left arrow key you cannot see UP arrow  but you can get another combinations of two arrow keys  AND viceversa if you hold together Left+ Up arrow key you cannot get spacebar keydown event
   1.3 holding Right arrow key you cannot see DOWN arrow  but you can get another combinations of two arrow keys AND viceversa if you hold together Right+ Down arrow key you cannot get spacebar keydown event

2. holding 2 arrow  keys
   2.1you cannot detect the third arrow key
(Yes here someone can affirm " But this is illogic, why must someone press and holding 3 arrow keys in the same moment?"
right as logic of programmer, wrong as function that must give back to me if a key is down and not if there is no more 2 key down!)
  2.2 you cannot detect spacebar when you press together Left+Up  or Right+Down...

in fact also using your newer array AS STRING *2  and  initializing as you have posted, I got the same result of you, the third key holded is not always got by I/O functions...
all this happens on a HP notebook 64bit windows 10  and CPU  AMD E 450 APU.

I'll test on another Notebook later
Title: Re: Odd multiple input problem
Post by: FellippeHeitor on July 11, 2019, 04:40:52 pm
It’s a hardware issue, TempodiBasic.
Title: Re: Odd multiple input problem
Post by: SMcNeill on July 11, 2019, 05:53:51 pm
_KEYDOWN is limited by hardware restrictions.  Most USB keyboards will never register any more than 6 keys simultaneously, due to USB specifications/limitations.  (Some might, but require either custom drivers, or multiple virtual drivers, and both options are unreliable.). You’d need a PS/2 N-key Keyboard to read more keys than that.

The best way to handle this type of input is to use _KEYHIT, instead of _KEYDOWN.

Use _KEYDOWN to check modifier keys (such as Shift-Ctrl-Alt with work with normal key presses), and _KEYHIT to handle normal keyboard input.

A nice write up on N-key keyboards, rollover, and USB limitations can be found here: http://blog.controlspace.org/2010/08/n-key-rollover-what-it-is-and-how-to.html
Title: Re: Odd multiple input problem
Post by: johannhowitzer on July 11, 2019, 06:41:22 pm
How does _KEYHIT function with holding keys down, though?  This game will involve holding down the arrow keys a lot for movement, and holding other keys as well for certain auxiliary functions.  All of this is moot at the end of the day for my purposes, of course, since I'll be moving to Unity for this project soon.  I appreciate the help, I've learned some important things here.
Title: Re: Odd multiple input problem
Post by: FellippeHeitor on July 11, 2019, 07:19:38 pm
KEYHIT returns a positive key code at key down, a negative key code at key up.

Wouldn’t likely help in the current case as the third key in the faulty combo won’t register in your hardware anyway.
Title: Re: Odd multiple input problem
Post by: Pete on July 11, 2019, 09:42:33 pm
Well, I don't know the PEEK state of the spacebar key, but I do know the value to detect Shift, Ctrl, and Alt; so, if you don't mid exchanging a Shift key for the spacebar, you could get a triple key detection with Windows API + a PEEK routine.

Code: QB64: [Select]
  1. CONST VK_LEFT = &H25
  2. CONST VK_UP = &H26
  3. CONST VK_SPACE = &H20
  4.  
  5.     FUNCTION GetAsyncKeyState% (BYVAL vkey%)
  6.     DEF SEG = 0
  7.     x = PEEK(&H417) MOD 16
  8.     DEF SEG
  9.  
  10.     _LIMIT 30
  11.     a%(0) = GetAsyncKeyState%(VK_LEFT)
  12.     a%(1) = GetAsyncKeyState%(VK_UP)
  13.     a%(2) = GetAsyncKeyState%(VK_SHIFT)
  14.     IF a%(0) AND a%(1) THEN
  15.         PRINT a%(0), a%(1), a%(2), x
  16.         IF a%(0) AND a%(1) AND x >= 1 AND x <= 3 THEN
  17.             PRINT "Arrow Left and Arrow Up and a Shift Key are all engaged!"
  18.         END IF
  19.     END IF
  20.  

Now if you read the 4 columns of values, you will notice the API cannot detect more than 2 keys down, which means the way I set up the code, it fails to detect the Shift key when the arrow up and left keys are depressed. Well, fortunately, the PEEK statement can detect a Shift key press, even when the arrow up and left keys are depressed; hence, a triple key routine is possible with Shift, and maybe with spacebar, if anyone can remember the PEEK DEF/SEG routine necessary to detect a space bar press.

Pete
Title: Re: Odd multiple input problem
Post by: TempodiBasic on July 12, 2019, 08:52:13 am
Hi
this is the results on another notebook
  [ This attachment cannot be displayed inline in 'Print Page' view ]  
yes on this program catch all _keydown in the same time!

and on the same TOSHIBA if I use an USB external Keyboard I have some other strange results!!


yes I must admit that it is an Hardware issue, no issue of language.
(@Fellippe Thanks for tips)
So both if I write something in C++ both in QB64 both in Python or whatdoyouwanttouse the results are the same depending on the hardware!!!
Title: Re: Odd multiple input problem
Post by: johannhowitzer on July 12, 2019, 01:14:45 pm
You've reminded me that I need to be careful of left+right or up+down inputs, thanks.
Title: Re: Odd multiple input problem
Post by: TempodiBasic on July 13, 2019, 11:16:16 am
Mhmmmm... _KEYDOWN is hardware sensible,
Steve and Fellippe suggest to use _KEYHIT knowing that if key is released _KEYHIT returns a negative value...

Mumble Mumble.... it let me imagine...

this is a first result of a my attempt to write a workaround with _keyhit at the place of _keydown

for now as you can see from image I can get to see 5 key pressed together and holding them...
  [ This attachment cannot be displayed inline in 'Print Page' view ]  
but I'm fighting with _KEYCLEAR, it is the first time that I use it.

Stay  cartooned / tuned
Title: Re: Odd multiple input problem
Post by: TempodiBasic on July 13, 2019, 11:57:21 am
Hi guys
I think that this is a good solution... only if someone let me see where I must put _KEYCLEAR to void the buffer's tail :-((

Code: QB64: [Select]
  1. CONST left = 1, right = 2, up = 3, down = 4, fire = 5, true = -1
  2. DIM arrow(1 TO 10) AS INTEGER, comm AS LONG, comms(1 TO 10) AS STRING
  3. arrow(left) = 19200
  4. arrow(right) = 19712
  5. arrow(up) = 18432
  6. arrow(down) = 20480
  7. COLOR 11, 2
  8.  
  9. PRINT (arrow(left)), (arrow(right)), (arrow(up)), (arrow(down))
  10.     CLS
  11.     comm = _KEYHIT ' memorize hardware input
  12.  
  13.     ' inizialize engine flag
  14.     IF comm > 0 THEN
  15.         ' key is pressed
  16.         IF (comm) = ((arrow(left))) THEN
  17.             comms(left) = STR$(true)
  18.         ELSEIF (comm) = ((arrow(right))) THEN
  19.             comms(right) = STR$(true)
  20.         ELSEIF (comm) = ((arrow(up))) THEN
  21.             comms(up) = STR$(true)
  22.         ELSEIF (comm) = ((arrow(down))) THEN
  23.             comms(down) = STR$(true)
  24.         END IF
  25.     ELSEIF comm < 0 THEN
  26.         ' key is released
  27.         IF (comm) = -((arrow(left))) THEN
  28.             comms(left) = ""
  29.         ELSEIF (comm) = -((arrow(right))) THEN
  30.             comms(right) = ""
  31.         ELSEIF (comm) = -((arrow(up))) THEN
  32.             comms(up) = ""
  33.         ELSEIF (comm) = -((arrow(down))) THEN
  34.             comms(down) = ""
  35.         END IF
  36.     END IF
  37.  
  38.  
  39.     ' engine
  40.     throw.x = 0
  41.     LOCATE 3, 1: PRINT "Xmove=";
  42.     IF VAL(comms(left)) = true THEN throw.x = -1: PRINT " Left   "
  43.     IF VAL(comms(right)) = true THEN throw.x = 1: PRINT " Right "
  44.  
  45.     throw.y = 0
  46.     LOCATE 5, 1: PRINT "Ymove=";
  47.     IF VAL(comms(up)) = true THEN throw.y = -1: PRINT " UP    "
  48.     IF VAL(comms(down)) = true THEN throw.y = 1: PRINT " Down "
  49.     IF throw.x = 0 AND throw.y = 0 THEN throw.x = 1
  50.  
  51.     IF comm = (32) AND spacepress = false THEN
  52.         spacepress = true
  53.         LOCATE 1, 1: PRINT "Spacepress="; spacepress; "  "
  54.         '     CALL spawn_shot(0, throw.x, throw.y)
  55.     ELSE
  56.         spacepress = false
  57.     END IF
  58.     IF comm = (27) THEN END
  59.     ' _KEYCLEAR
  60.     LOCATE 1, 1: PRINT "Spacepress="; spacepress; "   "
  61.     _LIMIT 10
  62.  
  63.  
Title: Re: Odd multiple input problem
Post by: Pete on July 13, 2019, 01:43:46 pm
Yes, the buffer is a huge problem when running the code. You can retrieve a single key entry by using _KEYCLEAR immediately after:    comm = _KEYHIT ' memorize hardware input

I'm surprised this worked for you, because on my system, it will not detect more than 2 keys when I use left arrow + up arrow + spacebar. Now some other combos work, but the one mentioned left arrow + up arrow + spacebar needs to work to have a breakthrough. I wish I could remember a way to get PEEK to recognize a spacebar press. In my attempt, I had to substitute Shift for the spacebar, so I really can't say if a way to PEEK a spacebar press would work or not. It just isn't apples to apples... more like Apples to Windows. Anyway, only certain PEEK/POKE are still preserved, as this was all 16-bit stuff, back in the day. I did find that PEEK(197) worked to find a key press on a Commador64, but that lower rage is apparently ignored on non-16 bit systems. Oh well, that's "progress" for you!

Pete

Title: Re: Odd multiple input problem
Post by: TempodiBasic on July 14, 2019, 01:18:05 pm
Hi Pete
about _KEYCLEAR
it doesn't solve the problem of the buffer

if I put it just after _KEYHIT I got a strange effect ON OFF for the key pressed without any detection if the key has hold or no.
If I put _KEYCLEAR in the area of waiting for new cycle after _LIMIT 10 and/or before _KEYHIT the program doesn't catch input from keyboard.
.....

about my workaround I have tested it using an USB keyboard and it can catch only 2 arrow keys and no more plus!
Also _KEYHIT seems to soffer of Hardware limitations.
In this case I think that also using PEEK  or INP there is no matter to do. Where the hardware fails there is not possible to use so combo! So for using  professional games with combo using plus 2 keys , the user must use a gamer keyboard with no limit (like PS/2 as said in the article linked by Steve).

Well at my home, if I want develop a game with such kind of combo (more than 2 keys) I must use one of the 2 notebook TOSHIBA that with their inner keyboard let me catch all the keys I like to catch. But if I use an USB keyboard (I have tested 2 keyboards USB and wireless made by different manufacter [Sigma, Trust]) I fall in the hardware issue.
While the 2 HP notebook  show the hardware issue also with their inner keyboard. 

Thank for reply Pete

In sum: the solution is  use a power hardware for gaming  or write a game with no such kind of combos.