Qbasicnews.com

Full Version: Key press delay . . .
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Since this forum has rekindled my playing with QB 4.5, I decided to try writing a very simple game, in the "Bomber" style.

The only problem I'm having though, is overcoming the delay after a key is pressed and held. Its the same thing that is desirable when typing, but NOT good in controlling a "ship". Big Grin

The only key-press commands I really know are INKEY$ and INPUT$(1).

Does anyone have any ideas on how to get around this?

Thanks all, Dex
That's one of the reasons to use a custom keyboard handler. There are lots of different "versions" for multikey handlers floating around there, check out the following authors: Milo Sedlacek, Joe Huber Jr., Eric Carr. I also tried Exposed Dreams' zKbh, and that works really nice.
Thanks Hex, but are these, perhaps posts prior to the great cracker-crash?

I'm not getting any search results for any of those names.

:???: Dex
You *can* overcome the annoying beep that comes with pressing out of the buffer by adding
Code:
Itemp$ = INKEY$

after the user presses a key.
Thanks agamemnus for that tip, but thats not actually my problem. I don't get any "beeps", just a delay after the first keypress.

For instance, I press the left arrow, my ship jumps ahead one "position" then pauses the standard key-delay time, then continues on smoothly. Each time I change direction, or start-and-stop, I have the same delay.

But, I'll keep searching. Big Grin

Dex
well.. that feeds empty stuff in the buffer, so maybe it will run smoother.
Also are you using an IF I$ <> "".... END IF loop?
Nope. You can read port &H60 for a simple, single-keypress keyboard handler. Now the codes are not ascii, but scancodes. A complete list of scancodes is in QB help:

Code:
ScanCodeOfLastKeyPressed% = INP(&H60)
NotUsed$=INKEY$  ' This clears keyboard

The response at port &H60 is immediate.
Yeah, Dex, but sometimes the almighty Google is the one who needs to be asked, not only the forum. :roll: Since you at least made the effort to search for these keywords, well... here we go with a classic: the legendary multikey code by Milo Sedlacek, with some sample code. MEGAMAN, TAKE NOTES ABOUT THIS ROUTINE!

Code:
DECLARE SUB KEYTEST ()
DECLARE FUNCTION MULTIKEY (T)

'ASM Interrupt & support code by Milo Sedlacek
'Demo by Joe Huber Jr.

'MULTIKEY - main routine
'    Usage:
'    X = MULTIKEY(T)
'    where t can equal -1,-2, and 1-128
'    t = -1: IMPORTANT!!!  Make sure you pass this value to
'             the function before -2 and 1-128!  It turns the
'             interrupt on so you can start reading keys.
'             Returns: nothing
'    t = -2: EXTREMELY IMPORTANT!!!!!!!!
'             ALWAYS pass this before you end your program!
'             If you don't, your computer won't be able to
'             read your keyboard & you'll have to reset!
'             i.e., CTRL-ALT-DEL won't work!!
'             Returns: nothing
'    t = keycode (1-128): Returns status of a key.
'             Returns: 1 or 0 where    
'                   1 = pressed
'                   0 = unpressed
'
'KEYTEST - helps you find new keycodes
'    Usage:
'    CALL KEYTEST or KEYTEST
'    This will show all 128 keycodes & their statuses.
'    Press & hold a key & a 1 will appear somewhere.
'    The number that the 1 is by will be the keycode
'    for that key.  Simple!

'Demo code:
'Use arrows to turn & accelerate
'Press space to come to a total stop
'Hit ESC to exit

Z = MULTIKEY(-1)    ' Initalize ASM & hook interrupt


SCREEN 12
CLS

X = 320
Y = 240
cPI = (3.141592654# / 180)
ANGLE = 0
RADIUS = 5
SPEED = .2
DO
        IF MULTIKEY(77) THEN ANGLE = ANGLE - 7 ' Left
        IF MULTIKEY(75) THEN ANGLE = ANGLE + 7 ' Right
        IF MULTIKEY(72) THEN                   ' Up
         VX = VX + (SIN(cPI * ANGLE) * SPEED)
         VY = VY + (COS(cPI * ANGLE) * SPEED)
        END IF
        IF MULTIKEY(80) THEN                   ' Down
         VX = VX - (SIN(cPI * ANGLE) * SPEED)
         VY = VY - (COS(cPI * ANGLE) * SPEED)
        END IF
        IF MULTIKEY(57) THEN                   ' Space
         VX = 0
         VY = 0
        END IF

        IF ANGLE > 360 THEN                   ' Wrap-around angle
         ANGLE = 0 + (ANGLE - 360)
        END IF
        IF ANGLE < 0 THEN
         ANGLE = 360 - (0 + ANGLE)
        END IF

        IF X < 0 + RADIUS THEN VX = -VX        ' Bounce limits
        IF X > 640 - RADIUS THEN VX = -VX
        IF Y < 0 + RADIUS THEN VY = -VY
        IF Y > 480 - RADIUS THEN VY = -VY
    
        X = X + VX                             ' Move it
        Y = Y + VY
      
        X2 = X + SIN(cPI * ANGLE) * RADIUS     ' White dot calc
        Y2 = Y + COS(cPI * ANGLE) * RADIUS     ' ditto
      
        VX = VX * .998                         ' Friction
        VY = VY * .998                         ' ditto
      
        CIRCLE (XX, YY), RADIUS, 0             ' Erase
        PSET (XX2, YY2), 0
        PSET (XX, YY), 0
        CIRCLE (X, Y), RADIUS, 4               ' Draw
        PSET (X2, Y2), 15
        PSET (X, Y), 4
        XX = X: YY = Y: YY2 = Y2: XX2 = X2
        WAIT &H3DA, 8                          ' Wait to vert. retarce
        WAIT &H3DA, 8, 8
LOOP UNTIL MULTIKEY(1) = 1                     ' Hit ESC to exit

Z = MULTIKEY(-2)         'Unhook interrupt

END

SUB KEYTEST

SCREEN 0
CLS

Z = MULTIKEY(-1)
DO
X = 1
Y = 1

FOR I = 1 TO 128

  TEST = MULTIKEY(I)
  LOCATE Y, X
  PRINT USING "## =###"; TEST; I

  IF Y < 23 THEN
   Y = Y + 1
  ELSE
   Y = 1
   X = X + 9
  END IF

NEXT I

LOOP WHILE MULTIKEY(1) = 0

Z = MULTIKEY(-2)

END

END SUB

FUNCTION MULTIKEY (T)

STATIC kbcontrol%(), kbmatrix%(), Firsttime, StatusFlag

IF Firsttime = 0 THEN          'Initalize
DIM kbcontrol%(128)
DIM kbmatrix%(128)
code$ = ""
code$ = code$ + "E91D00E93C00000000000000000000000000000000000000000000000000"
code$ = code$ + "00001E31C08ED8BE24000E07BF1400FCA5A58CC38EC0BF2400B85600FAAB"
code$ = code$ + "89D8ABFB1FCB1E31C08EC0BF2400BE14000E1FFCFAA5A5FB1FCBFB9C5053"
code$ = code$ + "51521E560657E460B401A8807404B400247FD0E088C3B700B0002E031E12"
code$ = code$ + "002E8E1E100086E08907E4610C82E661247FE661B020E6205F075E1F5A59"
code$ = code$ + "5B589DCF"
DEF SEG = VARSEG(kbcontrol%(0))
FOR I% = 0 TO 155                     ' Load ASM
     d% = VAL("&h" + MID$(code$, I% * 2 + 1, 2))
     POKE VARPTR(kbcontrol%(0)) + I%, d%
NEXT I%
I& = 16       ' I think this stuff connects the interrupt with kbmatrix%()
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
Firsttime = 1
END IF

SELECT CASE T
CASE -1
  IF StatusFlag = 0 THEN
   DEF SEG = VARSEG(kbcontrol%(0))
   CALL ABSOLUTE(0)                     ' Run interrupt
   DEF SEG
   StatusFlag = 1
  END IF
CASE -2
  IF StatusFlag = 1 THEN
   DEF SEG = VARSEG(kbcontrol%(0))      ' Turn off interrupt
   CALL ABSOLUTE(3)
   DEF SEG
   StatusFlag = 0
  END IF
CASE 1 TO 128
  MULTIKEY = kbmatrix%(T)               ' Return status
CASE ELSE
  MULTIKEY = 0                          ' User Stupidity Error
END SELECT

END FUNCTION
Thanks Hex, (and Nathan), I'll try these codes out as soon I get home.

Its funny, I actually did search Google for "Exposed Dreams", 'cause it sounded like a web page and/or company, but it didn't occur to me to check the individual names there. Sad

Thanks again, Dex
Mmmmm...., I tried to understand the code as I'm coping with a similar problem. But since I don't understand the peek, poke ( and a lot of other commands) I prefer to use simple ones. INKEY is slow. Another problem is that when I'm using two or four inkeys, only the first does work somewhat properly. The others are very difficult to get to work. Why is that?
Pages: 1 2