QB64 Phoenix Edition
Trapping two keys - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Code and Stuff (https://qb64phoenix.com/forum/forumdisplay.php?fid=3)
+---- Forum: Help Me! (https://qb64phoenix.com/forum/forumdisplay.php?fid=10)
+---- Thread: Trapping two keys (/showthread.php?tid=937)

Pages: 1 2


Trapping two keys - PhilOfPerth - 10-01-2022

Is there a command that can identify two keys pressed together, like up-curor+left-cursor? and if so, how can I ensure that enough time is allowed for any  slight discrepancy in the time they were pressed?


RE: Trapping two keys - bplus - 10-01-2022

_keydown(key number) will tell whether a particular key code is being pressed the moment you call it

So upArrow = _keydown(18432) ' IDE menu Tools > Insert Keycode gets 18432 when press up arrow
leftArrow = _keydown(19200)


RE: Trapping two keys - PhilOfPerth - 10-01-2022

I tried this, but it doesn't work:

get1:
k = _KeyHit
If k < 1 Then GoTo get1
get2:
l = _KeyHit
If l < 1 Then GoTo get2
n = k + l
Print l;
GoTo get1

Late edit: Thanks bplus; I didn't see your response til I edited my entry. I'll go and experiment with your explanation.


RE: Trapping two keys - bplus - 10-01-2022

kh& = _keyhit 'is fine too,
Select case kh& ' but _Keydown works great for detecting multiple keys
case 18432 ' then up arrow
if _keydown(19200) then ' up and left arrows both


RE: Trapping two keys - Pete - 10-01-2022

To demo what Mark is gettting at...

Code: (Select All)
DO
    _LIMIT 30
    IF _KEYDOWN(18432) THEN h = -1 ELSE h = 0
    IF _KEYDOWN(19200) THEN i = -1 ELSE i = 0
    IF h * i = 1 THEN PRINT "Both keys down." ELSE IF LEN(INKEY$) THEN CLS
    _KEYCLEAR
LOOP


I threw in the INKEY$ statement just to only clear the screen when a key is pressed, other than the combo you wanted, arrow up and left.

Now if you hold both down, the process will repeat. If you only want one event, then do this...

Code: (Select All)
DO
    _LIMIT 30
    IF _KEYDOWN(18432) THEN h = -1 ELSE h = 0
    IF _KEYDOWN(19200) THEN i = -1 ELSE i = 0
    IF h * i = 1 AND flag = 0 THEN
        PRINT "Both keys down."
        flag = -1
    ELSE
        IF h * i = 0 THEN flag = 0: CLS
    END IF
    _KEYCLEAR
LOOP

Hope that helps.

Pete


RE: Trapping two keys - PhilOfPerth - 10-01-2022

@Pete:
Yes, that does help. I'm starting to see the result I want now, but I'll need to fiddle around a bit. 
I want to detect and act on any of the 8 combinations for the cursor-keys.
I think this can be extended to do that. Thanks both.

Late edit: Nearly got it!

getKeys:
ky = 0
Do
    If _KeyHit < 1 Then GoTo getKeys
    If _KeyDown(18432) Then ky = ky + 1
    If _KeyDown(19200) Then ky = ky + 2
    If _KeyDown(19712) Then ky = ky + 4
    If _KeyDown(20480) Then ky = ky + 8
    Print ky
    _KeyClear
    _Limit 30
Loop


RE: Trapping two keys - Pete - 10-01-2022

Here are two examples that do the same thing, but have different coding formats...

Code: (Select All)
LINE INPUT "Input 1 for simple or 2 for complex demo: "; ans$
IF ans$ = "" THEN END
IF ans$ = "1" OR ans$ = "2" THEN ELSE BEEP: CLS: RUN
CLS
PRINT "Press any 2-combo of cursor arrow keys...": PRINT
IF ans$ = "1" THEN
    DO
        _LIMIT 30
        IF _KEYHIT < 1 THEN
            IF _KEYDOWN(18432) AND _KEYDOWN(19200) THEN
                IF flag = 0 THEN PRINT "a & b": flag = -1
            ELSEIF _KEYDOWN(18432) AND _KEYDOWN(19712) THEN
                IF flag = 0 THEN PRINT "a & c": flag = -1
            ELSEIF _KEYDOWN(18432) AND _KEYDOWN(20480) THEN
                IF flag = 0 THEN PRINT "a & d": flag = -1
            ELSEIF _KEYDOWN(19200) AND _KEYDOWN(19712) THEN
                IF flag = 0 THEN PRINT "b & c": flag = -1
            ELSEIF _KEYDOWN(19200) AND _KEYDOWN(20480) THEN
                IF flag = 0 THEN PRINT "b & d": flag = -1
            ELSEIF _KEYDOWN(19712) AND _KEYDOWN(20480) THEN
                IF flag = 0 THEN PRINT "c & d": flag = -1
            END IF
        END IF
        IF flag THEN
            a = _KEYDOWN(18432) + _KEYDOWN(19200) + _KEYDOWN(19712) + _KEYDOWN(20480)
            IF a = 0 THEN flag = 0: CLS
        END IF
    LOOP

ELSE ' Demo 2.

    REDIM flag(4)
    DO
        LOCATE 3, 1: PRINT "ky ="; ky
        _LIMIT 30
        IF flag2 = 0 THEN
            IF _KEYDOWN(18432) AND flag(1) = 0 THEN ky = ky + 1: flag(1) = -1
            IF _KEYDOWN(19200) AND flag(2) = 0 THEN ky = ky + 2: flag(2) = -1
            IF _KEYDOWN(19712) AND flag(3) = 0 THEN ky = ky + 4: flag(3) = -1
            IF _KEYDOWN(20480) AND flag(4) = 0 THEN ky = ky + 8: flag(4) = -1
        END IF
        IF ky THEN
            SELECT CASE ky
                CASE 3
                    IF flag2 = 0 THEN
                        PRINT "a & b"
                        flag2 = -1
                    ELSE
                        GOSUB flag_check
                    END IF
                CASE 5
                    IF flag2 = 0 THEN
                        PRINT "a & c"
                        flag2 = -1
                    ELSE
                        GOSUB flag_check
                    END IF
                CASE 6
                    IF flag2 = 0 THEN
                        PRINT "b & c"
                        flag2 = -1
                    ELSE
                        GOSUB flag_check
                    END IF
                CASE 9
                    IF flag2 = 0 THEN
                        PRINT "a & d"
                        flag2 = -1
                    ELSE
                        GOSUB flag_check
                    END IF
                CASE 10
                    IF flag2 = 0 THEN
                        PRINT "b & d"
                        flag2 = -1
                    ELSE
                        GOSUB flag_check
                    END IF
                CASE 12
                    IF flag2 = 0 THEN
                        PRINT "c & d"
                        pete = 1
                        flag2 = -1
                    ELSE
                        GOSUB flag_check
                    END IF
                CASE ELSE
                    GOSUB flag_off
            END SELECT
            _KEYCLEAR
        END IF
    LOOP

END IF ' Demo loop.

flag_check:
a = _KEYDOWN(18432) + _KEYDOWN(19200) + _KEYDOWN(19712) + _KEYDOWN(20480)
IF a = 0 THEN GOSUB flag_off
RETURN

flag_off:
ky = 0: REDIM flag(4): flag2 = 0: CLS
RETURN


Pete


RE: Trapping two keys - bplus - 10-01-2022

Just a note about _KeyClear, it won't help with _KeyDown(), it will clear Inkey$ or _KeyHit.

This is interesting:
Code: (Select All)
    If _KeyDown(18432) Then ky = ky + 1
    If _KeyDown(19200) Then ky = ky + 2
    If _KeyDown(19712) Then ky = ky + 4
    If _KeyDown(20480) Then ky = ky + 8
Instead of _KeyClear you could set ky = 0 but it would be more direct to just execute code like if left arrow then x = x-1 if right arrow then x = x+1, if up arrow then y = y - 1, if down arrow then y = y + 1.

You don't need any GetKey sub with _Keydown(), again it tells you immediately when key number is being held down.
Your problem with _keydown is going to be getting user to release key so several calls doing same thing aren't executed but my alternate suggestion is good for moving character around screen.

Quick HeroX, HeroY moving on screen:
Code: (Select All)
Screen _NewImage(800, 600, 32)
_ScreenMove 250, 50
heroX = 400: heroY = 300 ' middle
Do
    Cls
    Circle (heroX, heroY), 10
    If _KeyDown(19200) Then heroX = heroX - 5
    If _KeyDown(19712) Then heroX = heroX + 5
    If _KeyDown(18432) Then heroY = heroY - 5
    If _KeyDown(20480) Then heroY = heroY + 5
    _Limit 10
Loop



RE: Trapping two keys - Pete - 10-01-2022

Interesting about _KEYCLEAR. I never use _KEYDOWN, oh, there was that one time, but I didn't like it, so back to INKEY$. I like using _KEYCLEAR with INKEY$. It used to be a WHILE:WEND snippet was needed, or a null variable assigned to INKEY$ to have this type of effect on the key buffer. Nice to know it isn't needed with _KEYDOWN, even though I probably won't be using it in my own routines.

@PhilOfPerth just be aware in your attempt with ky values, they won't add up properly unless you take the ones held down out of the next iteration. If you've ever watched The Big Band Theory, this is where Sheldon Cooper says have, "Fun with Flags!" In the code I wrote for you in post #7, demo 2 in the single coded example uses (2) flags to control the ky addition process and to limit the print statement to just one printing while the key combo is held down. Demo one uses (1) flag variable in a more simplistic manner, just to recognize one operation was performed and no others will occur until the key combo is released.

Pete


RE: Trapping two keys - PhilOfPerth - 10-01-2022

That's great!
I liked the "simple" version better - it gave the same results for my application, and was clearer. Simple is always good for me, suits my personality.
I'm going to use that, with mods to trap single-cursor as well. May experiment with select case with it.