Author Topic: This Week's Dumb Question About Multiple Simultaneous INKEY$ Handling  (Read 4400 times)

0 Members and 1 Guest are viewing this topic.

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
I feel rather ashamed to ask this question (but that hasn't stopped me asking it!).  I am constructing a program where I'd like to allow 2 keys to be pressed at the same time, and for the program to recognise that with two different responses.

I don't suppose that that would be possible (either by INKEY$ or _KEYHIT).  How would the hardware be behaving?  How would the software recognise such?  If, by some remote possibility, this could be done in some way I shan't feel quite so dumb!  But pardon me for cluttering up the site with ridiculous questions (I'm trying to get the keyboard to have the property of a game controller left&right hand).  If I were Odin, I'd create a Special Section for Qwerkey's Stupid Questions with an automatic flushing facility.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Checkout _KEYDOWN, it reports when a key is down (or not) and is good for discerning key combinations.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Hi Qwerkey,
None of us is perfect and none of us knows everything. Which particular combinations would you like to try?

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
I handle stuff like that with PEEK and POKE. That way, I can highlight text if the shift key is held down and an arrow key is pressed, etc. If the _KEYDOWN doesn't work out, take a look at something I wrote many years ago. It still works in '64...

https://www.tapatalk.com/groups/qbasic/viewtopic.php?f=13959&t=30059&p=177576&hilit=def+seg#p177576

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

FellippeHeitor

  • Guest
I feel rather ashamed to ask this question (but that hasn't stopped me asking it!).  I am constructing a program where I'd like to allow 2 keys to be pressed at the same time, and for the program to recognise that with two different responses.

I don't suppose that that would be possible (either by INKEY$ or _KEYHIT).  How would the hardware be behaving?  How would the software recognise such?  If, by some remote possibility, this could be done in some way I shan't feel quite so dumb!  But pardon me for cluttering up the site with ridiculous questions (I'm trying to get the keyboard to have the property of a game controller left&right hand).  If I were Odin, I'd create a Special Section for Qwerkey's Stupid Questions with an automatic flushing facility.

Code: QB64: [Select]
  1. This:

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Thanks guys, it seems that I was so stupid that I hadn't realised that the Question wasn't actually that dumb!  Naturally, before posing the question here I had looked at the _KEYHIT, _KEYDOWN & _KEYCLEAR wiki pages, and assumed that the key combinations only worked for the Sys, ScL, Pause, CapL, Shift, Ctrl, Win, Alt & Menu keys in combination with other keys (they're the one in the wiki which have a "+" next to them, indicating their special combinatory abilities).

But I've now had a go with the example given on the _KEYDOWN wiki page, and indeed you DO seem to be able to have two keys down at once, and both the hardware and software can sort it out.  Quite amazing!

Petr, no need to worry about the mocking self-deprecation.  That's more-or-less the default British trait.  It's all done in the greatest of humour!

Pete, whenever I've seen other members' efforts with PEEK/POKE, I've never understood a thing.

« Last Edit: June 12, 2019, 12:15:24 pm by Qwerkey »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
You can also use _KEYHIT to track multiple key presses.  Remember, _KEYHIT gives us TWO values for each keypress — one when the key is pressed down, and a negative value for when the key is released.

Instead of storing the KEYHIT in a single variable (such as just K = _KEYHIT), instead you save it into an array of keys down, and then remove it from the array when keys are let up.

I can give an example, if you’re curious, once I get back home and at my PC later.  (Currently, I’m in town, on my iPad, which is impossible for me to code much from.)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Steve, thanks.  I'll work with _KEYDOWN for the present, using the wiki page example as my guide.  You'll hear from me, no doubt, if I'm struggling.

None of us is perfect and none of us knows everything.

Petr, there you are quite wrong.  Steve McNeill not only knows everything, but he understands everything!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
A quick demo of how one could use _KEYHIT to track multiple key presses at the same time, for those who might be curious about the process:

Code: QB64: [Select]
  1. DIM KeysDown(10)
  2.     k = _KEYHIT
  3.     SELECT CASE k
  4.         CASE IS > 0 'key is pressed down
  5.             AlreadyDown = 0 'Assume it's not recorded as down, by default
  6.             FOR i = 1 TO KeysDown(0) 'check to see if the key is already recorded as "down"
  7.                 IF k = KeysDown(i) THEN
  8.                     AlreadyDown = -1 'It's already down
  9.                     EXIT FOR
  10.                 END IF
  11.             NEXT
  12.             IF NOT AlreadyDown THEN
  13.                 KeysDown(0) = KeysDown(0) + 1 '0th element is to track how many keys are down
  14.                 KeysDown(KeysDown(0)) = k 'elements 1 to 10 represent the keys which are actually down
  15.             END IF
  16.         CASE IS < 0 'key is released
  17.             FOR i = 1 TO 10
  18.                 IF KeysDown(i) = -k THEN 'remove the key from the array as it's lifted up
  19.                     FOR j = i TO 9
  20.                         KeysDown(j) = KeysDown(j + 1)
  21.                     NEXT
  22.                     KeysDown(0) = KeysDown(0) - 1 'subtract the total numbers of keys held down from our counter
  23.                     EXIT FOR
  24.                 END IF
  25.             NEXT
  26.         CASE 0 ' we don't do anything if there's no keys being held/released
  27.     END SELECT
  28.  
  29.     'Display some results
  30.     CLS
  31.     PRINT "There are currently"; KeysDown(0); " keys being held down."
  32.     FOR i = 1 TO KeysDown(0)
  33.         PRINT KeysDown(i)
  34.     NEXT
  35.  
  36.     _DISPLAY 'reduce flicker
  37.     _LIMIT 30 'reduce CPU usage
  38. LOOP UNTIL ESCAPE
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
So getting this into something useful like my highlighting example, this is what came to my mind, first...

Find out if either shift key is held down while a right or left arrow key is pressed

Code: QB64: [Select]
  1. DIM KeysDown(10)
  2. GOSUB dsp
  3.     k = _KEYHIT
  4.     SELECT CASE k
  5.         CASE IS > 0 'key is pressed down
  6.             AlreadyDown = 0 'Assume it's not recorded as down, by default
  7.             FOR i = 1 TO KeysDown(0) 'check to see if the key is already recorded as "down"
  8.                 IF k = KeysDown(i) THEN
  9.                     AlreadyDown = -1 'It's already down
  10.                     EXIT FOR
  11.                 END IF
  12.             NEXT
  13.             IF NOT AlreadyDown THEN
  14.                 KeysDown(0) = KeysDown(0) + 1 '0th element is to track how many keys are down
  15.                 KeysDown(KeysDown(0)) = k 'elements 1 to 10 represent the keys which are actually down
  16.             END IF
  17.             GOSUB dsp
  18.         CASE IS < 0 'key is released
  19.             FOR i = 1 TO 10
  20.                 IF KeysDown(i) = -k THEN 'remove the key from the array as it's lifted up
  21.                     FOR j = i TO 9
  22.                         KeysDown(j) = KeysDown(j + 1)
  23.                     NEXT
  24.                     KeysDown(0) = KeysDown(0) - 1 'subtract the total numbers of keys held down from our counter
  25.                     EXIT FOR
  26.                 END IF
  27.             NEXT
  28.             GOSUB dsp
  29.         CASE 0 ' we don't do anything if there's no keys being held/released
  30.     END SELECT
  31.     _LIMIT 30 'reduce CPU usage
  32. LOOP UNTIL ESCAPE
  33.  
  34. dsp:
  35. 'Display results
  36. PRINT "There are currently"; KeysDown(0); "keys being held down."
  37. FOR i = 1 TO KeysDown(0)
  38.     PRINT KeysDown(i)
  39.  
  40. _DISPLAY 'reduce flicker
  41.  
  42. ' See if shift and left arrow are down
  43. IF KeysDown(0) = 2 THEN
  44.     IF KeysDown(1) + KeysDown(2) >= 100303 + 19200 AND KeysDown(1) + KeysDown(2) <= 100304 + 19200 THEN
  45.         PRINT "Highlighting left initiated!"
  46.         _DISPLAY
  47.         _DELAY 1
  48.     ELSEIF KeysDown(1) + KeysDown(2) >= 100303 + 19712 AND KeysDown(1) + KeysDown(2) <= 100304 + 19712 THEN
  49.         PRINT "Highlighting right initiated!"
  50.         _DISPLAY
  51.         _DELAY 1
  52.     END IF
  53.  

Now maybe there is some "bitwise" way of calculating combined values, which is better than what I presented here. Like I stated, I still use PEEK/POKE routines for these activities. In an actual WP, you have to add highlighting up and down methods, too. Anyway, it's what I love about BASIC, there's more than one way to peel a banana.

800lb gorilla out,

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: This Week's Dumb Question About Multiple Simultaneous INKEY$ Handling
« Reply #10 on: June 11, 2019, 04:58:14 pm »
Steve's code looks like handy way to get key code numbers.

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: This Week's Dumb Question About Multiple Simultaneous INKEY$ Handling
« Reply #11 on: June 12, 2019, 03:31:32 am »
Just to confirm, I have included a sequence of _KEYDOWN statements in my code and indeed more than 1 key pressed at the same time has multiple consequences which QB64 handles perfectly.  Wow!

Offline Raven_Singularity

  • Forum Regular
  • Posts: 158
    • View Profile
Re: This Week's Dumb Question About Multiple Simultaneous INKEY$ Handling
« Reply #12 on: June 12, 2019, 12:06:53 pm »
Just to add to this:

The number of simultaneous key-downs that a system can handle is determined by the actual keyboard hardware.  The most advanced USB keyboards allow detection of key up/down states for EVERY key simultaneously.  With cheap keyboards, sometimes even 3 simultaneous keypresses can fail!  All keyboards can handle Ctrl, Alt, Shift combinations because OSes so commonly use them as modifiers, but once you get into uncommon combinations like A+B+C, it's much less likely to register the keypresses.

Also to note, PS/2 and the original keyboard connectors physically limit how many keypresses can be sent simultaneously.  USB keyboards, in theory, have no such limits, but in practise most cheap USB keyboards emulate PS/2 under-the-hood, along with their crappy limitations.  Gaming keyboards often advertise how many keys can be held down simultaneously, though some lie about this!  My current piece-of-shit Amazon Basics keyboard is terrible for this, it often fails with three-key combos, despite saying it can handle 128 simultaneous keys or some rubbish.

Back in the day I can remember trying tons of key combos to figure out which could be handled for multiplayer gaming on the same keyboard.  It was tricky to find keys that wouldn't block each other.
« Last Edit: June 12, 2019, 12:14:16 pm by Raven_Singularity »

Offline Jack002

  • Forum Regular
  • Posts: 123
  • Boss, l wanna talk about arrays
    • View Profile
Re: This Week's Dumb Question About Multiple Simultaneous INKEY$ Handling
« Reply #13 on: June 12, 2019, 12:11:28 pm »
Years ago I was looking at this topic for the commodore 64. Even two keypresses were not always detectable. There were row and column wires and when you pressed one key the pressing of others was hidden. Not a think on a c64, I am surprised you can do it on any keyboard.
QB64 is the best!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: This Week's Dumb Question About Multiple Simultaneous INKEY$ Handling
« Reply #14 on: June 12, 2019, 02:24:47 pm »
Just to add to this:

The number of simultaneous key-downs that a system can handle is determined by the actual keyboard hardware.  The most advanced USB keyboards allow detection of key up/down states for EVERY key simultaneously.  With cheap keyboards, sometimes even 3 simultaneous keypresses can fail!  All keyboards can handle Ctrl, Alt, Shift combinations because OSes so commonly use them as modifiers, but once you get into uncommon combinations like A+B+C, it's much less likely to register the keypresses.

Also to note, PS/2 and the original keyboard connectors physically limit how many keypresses can be sent simultaneously.  USB keyboards, in theory, have no such limits, but in practise most cheap USB keyboards emulate PS/2 under-the-hood, along with their crappy limitations.  Gaming keyboards often advertise how many keys can be held down simultaneously, though some lie about this!  My current piece-of-shit Amazon Basics keyboard is terrible for this, it often fails with three-key combos, despite saying it can handle 128 simultaneous keys or some rubbish.

Back in the day I can remember trying tons of key combos to figure out which could be handled for multiplayer gaming on the same keyboard.  It was tricky to find keys that wouldn't block each other.

The term of importance here is, “key rollover”.  https://en.m.wikipedia.org/wiki/Rollover_(key)

Most keyboards are listed with a “#-key rollover” rating.  (Or #KRO.)  A very cheep keyboard is called a 2KRO and allows simultaneous pressing of 2 keys.  A standard keyboard is often a 4KRO (4 key presses allowed), and many gaming keyboards are 6KRO.  The truly expensive keyboards which allow EVERY key to be pressed and handled at once are called NKRO.  (n-key rollover)

From my personal experience, most USB keyboards top out at 6KRO, while you need a PS/2 keyboard for NKRO usage.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!