Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to use 2+ keys at once to do 2+ thing at once 2

Status
Not open for further replies.

Icaerus

Programmer
Dec 18, 2002
2
US
I'm writing a top down scroller I would like to use the up arrow and the left arrow to make my sprite go diagonal.
I already know how CHAR numbers but I can only use one at a time my code:

PRESS$=INKEY$
IF PRESS$= CHR$(116) THEN GOSUB FORWARD
IF PRESS$= CHR$(71) THEN GOSUB BACK
IF PRESS$= CHR$(70) THEN GOSUB LEFT
IF PRESS$= CHR$(73) THEN GOSUB RIGHT
(Also this setup is very laggy it takes a second to respond)
any help would be great.
 
Forget inkey$...
use this...

Code:
DECLARE SUB SETKEYS ()
DECLARE SUB CLEARBUF ()
DECLARE SUB GETKEYS ()

CONST TRUE = -1: FALSE = 0

Dim SHARED KB(128), lastk
'THESE ARE OPTIONAL ALONG WITH THE SETKEYS SUB...
Dim SHARED KBUP, KBDOWN, KBLEFT, KBRIGHT, KBESC, KBLSHIFT, KBRSHIFT, KBCTRL, KBSPACE, KBALT
SETKEYS


'USAGE EXAMPLE...
Do
GETKEYS 'GET KEYBOARD INPUT
LOCATE 3, 1: Print "KEYBOARD: UP KB(72)="; KB(72); " DOWN KB(80)="; KB(80); " LEFT KB(75)="; KB(75); " RIGHT KB(77)="; KB(77)
LOCATE 4, 1: Print " ALT KB(56)="; KB(56); " CTRL KB(29)="; KB(29); " SPACE KB(57)="; KB(57); " "
Loop Until KB(KBESC) 'END ON ESC
End
Code:
Sub CLEARBUF()
  DEF SEG = &H40
  POKE &H1A, PEEK(&H1A + 2)
'  or use this...
'  FOR N = 0 TO 10: S$ = INKEY$: NEXT
End Sub

'This Is the Main Sub that does all the work
Sub GETKEYS()
  K = INP(96)
  If K Then                  'KEY CHANGED
    If K < 128 Then          'KEY PRESSED
      KB(K) = True           'SET THE KEY
      lastk = K              'SET THE LAST KEY PRESSED MARKER
    Else                     '....ELSE...LAST KEY RELEASED
      If K = 170 Then        'NOTE: (SC) 170 IS RELEASE LAST KEY PRESSED
        KB(lastk) = False    'CLEAR LAST KEY PRESSED
      Else                   '...ELSE...OTHER KEY RELEASED
        KB(K - 128) = False  'CLEAR RELEASED KEY
      End If
    End If
  End If
  CLEARBUF 'CLEAR REGULAR KEY BUFFER KEY BUFFER (NO BEEPS)
End Sub
'These are optional
Sub LEARNKEY()
'THIS SUB IS FOR USE IN THE IMMEDIATE WINDOW
'*** NOTE YOU MUST RUN THE PROGRAM FIRST
KB(1) = 0
Do
GETKEYS
LOCATE 1, 1: Print &quot;PRESS A KEY FOR SCAN CODE BELOW&quot;
LOCATE 2, 1: Print lastk
Loop Until KB(1)
End Sub

Sub SETKEYS()
KBUP = 72
KBDOWN = 80
KBLEFT = 75
KBRIGHT = 77
KBESC = 1
KBLSHIFT = 42
KBRSHIFT = 54
KBCTRL = 29
KBSPACE = 57
KBALT = 56
End Sub

Gotta LuV multiKey Input...
Visit my site for full input program including mouse and some gamepad input...
this file is located at:

Thanks,
-Josh Stribling
cheers.gif
 
very easy to do.

here's a very basic scroller. i'm assuming you have all the subs.

common shared press as integer


press = inp(&h60) '(&h60) points to the keyboard buffer or something like that...

select case press
case 72
pressupkey

case 80
pressdownkey

case 75
pressleftkey

case 77
pressrightkey

end select
loop until press = chr$(27) 'esc key


that's for the four keys. add this after your all those cases.

case 77 and 72
pressupandrightkey

and so on.

subpressupandrightkey


'assuming that this is a tile scrolling engine...

px = px + 1 'player x position on screen
py = py - 1 'player y position on screen

'i'm assuming that the tiles are 20*20. if they're something else,
'change the twenty on the bottom to what the dimensions are in order.
redrawscreen 'so you don't get an after image.
put (px * 20, py * 20)player, pset

'or if you're using masks...

put (px * 20, py * 20)playermask, and
put (px * 20, py * 20)player, or

'changing px and py at the same time moves the player diagonally. if you're using a pixel*tile scroller...


'zy is the movement of the player's y coordinates, pixel by pixel.
'zx is the movement of the player's x coordinates, pixel by pixel.

submoveplayerupright
do
zy = zy + 1
zx = zx + 1

if zy = 20 and zx = 20 then
px = px + 1 'px takes over from zx
py = py - 1 'py takes over from zy
zy = 0 'put zy to zero so we can exitthe loop
zx = 0 'put the zx to zero so we can exit the loop
endif

redrawscreen
put (px + 20 + zx, py * 20 - zy)player, pset

loop until zy = 0 and zx = 0
endsub


that should clear things up... if it doesn't, tell me. i haven't tested it. i am not certain what it'll do... if it doesn't work, try assigning a second PRESS and do the same thing with the original press
(press = inp(&h60): press2 = inp(&h60)

that MIGHT work... e-mail me at marshall_7ca@yahoo.ca and we can talk.
 
No... You're leaving a few things out...

You are only checking for key presses... No releases (key + 128)...
And you are not saving the last Key Pressed and releasing it with the 170 event... (when press = 170)

with this Code it will continue to scroll until you press another button... (plus... ESC is key 1, not chr$(27))

Not to mention the fact that you are NOT clearing the keyboard buffer wich WILL result in annoying beeps...

Using the same code, and my sub from above, this is what it needs to look like this...

Code:
DECLARE SUB SETKEYS ()
DECLARE SUB CLEARBUF ()
DECLARE SUB GETKEYS ()

CONST TRUE = -1: FALSE = 0

Dim SHARED KB(128), lastk

Dim SHARED KBUP, KBDOWN, KBLEFT, KBRIGHT, KBESC, KBLSHIFT, KBRSHIFT, KBCTRL, KBSPACE, KBALT
SETKEYS

px = 160
py = 100
Do
  ox = px
  oy = py
  GETKEYS   'GET KEYBOARD INPUT
Code:
  if KB(KBUP) then
    py = py - 1
  end if

  if KB(KBDOWN) then
    py = py + 1
  end if

  if KB(KBLEFT) then
    px = px - 1
  end if

  if KB(KBRIGHT) then
    px = px + 1
  end if
Code:
  if (px <> ox) or (py <> oy) then
    'move the character
    'draw the screen...
  end if

  'all your other code here...

Loop Until KB(KBESC) 'END ON ESC
End

Sub CLEARBUF()
  DEF SEG = &H40
  POKE &H1A, PEEK(&H1A + 2)
End Sub

'This Is the Main Sub that does all the work
Sub GETKEYS()
  K = INP(96)
  If K Then                  'KEY CHANGED
    If K < 128 Then          'KEY PRESSED
      KB(K) = True           'SET THE KEY
      lastk = K              'SET THE LAST KEY PRESSED MARKER
    Else                     '....ELSE...LAST KEY RELEASED
      If K = 170 Then        'NOTE: (SC) 170 IS RELEASE LAST KEY PRESSED
        KB(lastk) = False    'CLEAR LAST KEY PRESSED
      Else                   '...ELSE...OTHER KEY RELEASED
        KB(K - 128) = False  'CLEAR RELEASED KEY
      End If
    End If
  End If
  CLEARBUF 'CLEAR REGULAR KEY BUFFER KEY BUFFER (NO BEEPS)
End Sub

Sub SETKEYS()
  'These are common keys...
  KBUP = 72     'Up Arrow
  KBDOWN = 80   'Down Arrow
  KBLEFT = 75   'Left Arrow
  KBRIGHT = 77  'right Arrow
  KBESC = 1     'Esc Key
  KBLSHIFT = 42 'Left Shift
  KBRSHIFT = 54 'Right Shift
  KBCTRL = 29   'Ctrl Key
  KBSPACE = 57  'Space Bar
  KBALT = 56    'Alt Key
End Sub

with that code, you can:
press right to scroll over...
press up at the same time to change directions to diagonal...
release right to just scroll up...
etc...

This is the way you NEED to write the code to make it work CORRECTLY... Sometimes... the BASIC things in life are the best...
cheers.gif

or at least the most fun ;-)
-Josh Stribling
 
I HOPE IT WORKS BUT YOU CAN USE THIS LITTLE PROGRAM
PSET(0,0)
DO
DO
KEY$ =INKEY$
LOOP UNTIL KEY$ <>&quot;&quot;
NUMKEY%=ASC(RIGHT$(KEY$,1))
SELECT CASE NUMKEY%
CASE 72 upkey
y =y+1
CASE 80 downkey
y = y-1
CASE 75 leftkey
x = x-1
CASE 77 rightkey
x =x+1
CASE ELSE
END SELECT
PSET (X,Y)
LOOP UNTIL NUMKEY% = 27 (esc key)
 
Inkey$ is a single key function...

to use multikey you have to write your own...

to write your own you have to use INP(96) aka INP(&H60)... (&H60 = 96)

to use INP(96) you have to know EVERYTHING that is going on...

What is returned when, and why it is returned...

your best bet is to use the code I placed above...

If you don't understand a part of it, just let me know...

THNX,
Josh Have Fun, Be Young... Code BASIC
-Josh Stribling
cubee101.gif

 
I've used INP(96) for along time now for the input from the keyboard buffer and I've only been able to do multikey inputs buy saving the last key and I used press = inkey$ to get rid of those stupid beeps, but I've been wondering is there a way to monitor the keyboard with the Peek command? If anyone knows please tell me. THX
 
I don't think there is...

INP function, if you read the help file, is a function that reads a byte from a device I/O port... (not memory)

PEEK/POKE read/write to and from memory...

just like an interupt can not be accessed with peek/poke...

they are all different parts of the processor...

Now you might be able to write some sort of Assembly routine to use, if you are worried about speed... but I believe the answer to the Peek question is NO...

Sorry :-(

But... If I am wrong, and someone does know a way, I would also like to know...

Have Fun, Be Young... Code BASIC
-Josh Stribling
cubee101.gif

 
Well, I did find a way to monitor the ctrl, alt, caps, num lock, scroll lock, and insert keys using

DEF SEG = 0
DO
A = PEEK(1047)
B = INP(96)
LOCATE 1
PRINT A
LOOP UNTIL B = 1
DEF SEG

This works well. I also found a way to montor te rest of the keyboard using PEEK (It took me forever after testing and testing), but it doesn't work that good (all it can do is tell if a key has been pressed):

DEF SEG = 0
DO
A = PEEK(1050)
B = PEEK(1052)
C = INP(96)
LOCATE 1
PRINT A
LOCATE 2
PRINT B
LOOP UNTIL C = 1
DEF SEG

PEEK(1050) and PEEK(1052) I think do the same thing.
The problem with this is that it only tells if a key (other than ctrl, alt, caps, etc...) has beenn pressed and not which one.
 
I was doin experiments and found out PEEK(1050) and PEEK(1052) is just the keyboard buffer thing because if you add INKEY$ anywhere in the code the numbers reset (because INKEY$ clears out the keyboard buffer). So all that is is the keyboard buffer I think.
 
*reads old post up top, hits his head*
god, what a noob i was. I can't stand to read that! *bangs head some more*

good call cube. just wish you took a bit more out of me, like calling me a noob and making fun of my pretend multikey knowledge. ;)

oh, your welcome icaerus, although i never did squat ;)
 
Lol...
Yeah, I was looking at those dates earlier today also...

Man, It doesn't seem like a year ago...

But the programming scene is always changing and people are constantly finding better ways of doing things...

So you are always learning...

And I (still) think the best way to learn is by trial and error (and other people correcting your errors ;-))

I think I even had a typo up there...

I don't think this line is entirely true... ;-)
with this Code it will continue to scroll until you press another button

Have Fun, Be Young... Code BASIC
-Josh
cubee101.gif

 
who wrote that originally? if it was me, i'm banging my head some more :p

yes, the memories... tek-tips was fairly popular back then as well. too bad people don't stay long...

maybe tek tip's a bit too strict for them? (you know, the policy of only making code related topics, deleting posts that don't fit or advertise or whatever (i agree witht he ad and homework policy though!)
 
Yeah, I have developed my skills quite a bit since I have been using Tek-Tips...

You get some people asking how to do some off the wall stuff and it gets your gears spinning...
Before you know it you have a solution figured out and you are able to answer the person's question and also learn something at the same time ;-)

I agree with the Ad & HomeWork Policy too...

I am glad to see the Qbasic comunity growing again...

It seemed like there were no posts at all for about 6 months or so...

Qbasic is a good stepping stone for jumping into VB, which is a VERY powerful tool...

I have managed to link just about Every Program that we use at work together via Visual Basic ;-)
Which in turn saves alot of time from repeating stuff...

(Not to mention the challenge of pushing a dos interpreter to the limits for games and stuff ;-))

Have Fun, Be Young... Code BASIC
-Josh
cubee101.gif

 
If you use INKEY$ or INP(96) it will pause before repeating, so screw them both, this multikey routine uses assembly, it DOES NOT PAUSE, and you can use as many keys at a time as you want.

DECLARE SUB offkb ()
DECLARE SUB onkb ()
DECLARE SUB readassembly ()
REDIM kbcontrol%(128), kbmatrix%(128)
readassembly
onkb
DO
CLS
LOCATE 1
FOR a% = 0 TO 128
IF kbmatrix%(a%) THEN PRINT a% '<- tells you which key(s) are being pressed
IF kbmatrix%(1) THEN offkb: END '<- Press Esc to leave
NEXT
LOOP

kbdata:
DATA &HE9,&H1D,&H00,&HE9,&H3C,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00,&H00
DATA &H00,&H00,&H00,&H00,&H1E,&H31,&HC0,&H8E,&HD8,&HBE,&H24,&H00,&H0E,&H07
DATA &HBF,&H14,&H00,&HFC,&HA5,&HA5,&H8C,&HC3,&H8E,&HC0,&HBF,&H24,&H00,&HB8
DATA &H56,&H00,&HFA,&HAB,&H89,&HD8,&HAB,&HFB,&H1F,&HCB,&H1E,&H31,&HC0,&H8E
DATA &HC0,&HBF,&H24,&H00,&HBE,&H14,&H00,&H0E,&H1F,&HFC,&HFA,&HA5,&HA5,&HFB
DATA &H1F,&HCB,&HFB,&H9C,&H50,&H53,&H51,&H52,&H1E,&H56,&H06,&H57,&HE4,&H60
DATA &HB4,&H01,&HA8,&H80,&H74,&H04,&HB4,&H00,&H24,&H7F,&HD0,&HE0,&H88,&HC3
DATA &HB7,&H00,&HB0,&H00,&H2E,&H03,&H1E,&H12,&H00,&H2E,&H8E,&H1E,&H10,&H00
DATA &H86,&HE0,&H89,&H07,&HE4,&H61,&H0C,&H82,&HE6,&H61,&H24,&H7F,&HE6,&H61
DATA &HB0,&H20,&HE6,&H20,&H5F,&H07,&H5E,&H1F,&H5A,&H59,&H5B,&H58,&H9D,&HCF,-1

SUB offkb
SHARED keyboardonflag%, kbcontrol%()
IF (keyboardonflag% = 0) THEN EXIT SUB
keyboardonflag% = 0
DEF SEG = VARSEG(kbcontrol%(0))
CALL Absolute(3)
DEF SEG
END SUB

SUB onkb
SHARED kbcontrol%(), keyboardonflag%
IF keyboardonflag% THEN EXIT SUB
keyboardonflag% = 1
DEF SEG = VARSEG(kbcontrol%(0))
CALL Absolute(0)
DEF SEG
END SUB

SUB readassembly
SHARED kbcontrol%(), kbmatrix%()
RESTORE kbdata
DEF SEG = VARSEG(kbcontrol%(0))
I& = 0
GOTO skip0
DO
POKE I&, q%
I& = I& + 1
skip0:
READ q%
LOOP WHILE q% > -1
I& = 16
n& = VARSEG(kbmatrix%(0))
l& = n& AND 255
h& = ((n& AND &HFF00) \ 256)
POKE I&, l&
POKE I& + 1, h&
I& = I& + 2
n& = VARPTR(kbmatrix%(0))
l& = n& AND 255
h& = ((n& AND &HFF00) \ 256)
POKE I&, l&
POKE I& + 1, h&
I& = I& + 2
DEF SEG
END SUB

This is the same code that is in my FAQ, for future reference.
 
Wow even i was on this way back in May when I was a complete and stupid newbie (not that I'm not now cause i still am). its funny people have been replying to posts from years back lately.
 
Well there is always discussion about the best ways to do something, that the only way to make advances.
 
Hey, I'm a noob here. I'm using qbasicking's keyboard routine for a platform game, and it works great except for one strange problem. Using the arrow keys (but NOT the numpad arrow keys) turns on not only 72, 75, 77, and 80, but 42 (left shift) as well. Since I wanted to use left shift as a speed control (hold to run), this obviously presents a problem, in that the player runs regardless of whether shift is pressed. It's worth mentioning that pressing and releasing the left shift key fixes the problem, at least until the next time the arrow key is pressed.

Since I haven't seen any mention of this kind of problem before, I'm seriously wondering if it's just my keyboard acting weird. I tried Cube's code and had the same problem. But if there's any help to be had, I'd appreciate it.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top