Page 1 of 1
Keyboard buffer problem
Posted: Tue Nov 30, 2010 8:53 pm
by ThirtyNitesOfMX
for my main walking engine, im using INP(96) which seems to work fine other than the anomaly with releasing 2 buttons at once and the CPU missing one of the keyUP inputs.
however, ill call a subroutine where i prefer using key$ = inkey$, it makes more sense for battle menus, item menus, etc.
the problem is, when the subroutine is finished and it goes back to the main walking engine, all the keystrokes have been saved in the buffer and the character walks around in all the directions i moved the cursor in the menu sub, until the buffer is clear.
i have heard of one way to wipe the keyboard buffer to eliminate this problem, using this code
DEF SEG = &H40
POKE &H1A, PEEK(&H1A + 2)
i have it right before
k = inp(96)
it is obviously not doing what it is supposed to. in fact, im not sure its doing anything.
my first instinct was to write a subroutine which is called at the end of every sub which uses key$ for the keyboard input and just lets the keyboard buffer blow its load there, but obviously its not going to clear out until i go back to my main engine and it unloads in the walking sequence.
any thoughts? anybody ever successfully tackled this problem?
maybe im just not putting the:
DEF SEG = &H40
POKE &H1A, PEEK(&H1A + 2)
..in the right place?
thanks.
Posted: Tue Nov 30, 2010 9:46 pm
by ThirtyNitesOfMX
i was just looking at the source code for qb64
shouldnt &h40 be &H60? since 60 = 96 in hex...
Posted: Tue Nov 30, 2010 9:48 pm
by burger2227
THAT is for using PEEK to read the Function keys like Caps Lock, Scroll Lock, Number Lock, etc.
You can't POKE newer PC keyboards! Not even XP...
Try this Multikey Function I made:
Code: Select all
DECLARE FUNCTION ScanKey%(code%) 'NOT required in QB64
CLS
LOCATE 8, 14: PRINT "W A S D": LOCATE 8, 52: PRINT "ARROW PAD"
DO: _LIMIT 1000 ' program or game loop
IF ScanKey%(17) THEN LOCATE 2, 15: PRINT " UP " ELSE LOCATE 2, 15: PRINT "----" 'W key
IF ScanKey%(31) THEN LOCATE 6, 15: PRINT "DOWN" ELSE LOCATE 6, 15: PRINT "----" 'S key
IF ScanKey%(30) THEN LOCATE 4, 12: PRINT "LEFT" ELSE LOCATE 4, 12: PRINT "----" 'A key
IF ScanKey%(32) THEN LOCATE 4, 18: PRINT "RIGHT" ELSE LOCATE 4, 18: PRINT "---- " 'D key
IF ScanKey%(72) THEN LOCATE 2, 55: PRINT " UP " ELSE LOCATE 2, 55: PRINT "----" 'arrow
IF ScanKey%(80) THEN LOCATE 6, 55: PRINT "DOWN" ELSE LOCATE 6, 55: PRINT "----" 'arrow
IF ScanKey%(75) THEN LOCATE 4, 52: PRINT "LEFT" ELSE LOCATE 4, 52: PRINT "----" 'arrow
IF ScanKey%(77) THEN LOCATE 4, 58: PRINT "RIGHT" ELSE LOCATE 4, 58: PRINT "---- " 'arrow
LOOP UNTIL ScanKey%(1)
zerocodes% = ScanKey%(0) 'reset all array values to zero for next part of program
END
FUNCTION ScanKey% (scancode%)
STATIC Ready%, keyflags%()
IF NOT Ready% THEN REDIM keyflags%(0 TO 127): Ready% = -1
i% = INP(&H60) 'read keyboard states
IF (i% AND 128) THEN keyflags%(i% XOR 128) = 0
IF (i% AND 128) = 0 THEN keyflags%(i%) = -1
K$ = INKEY$
ScanKey% = keyflags%(scancode%)
IF scancode% = 0 THEN Ready% = 0 'allows program to reset all values to 0 with a REDIM
END FUNCTION
Use scancode% = 0 to reset the Array on the next use.
erasearray% = ScanKey%(0) 'resets Ready% in function
Ted
Posted: Tue Nov 30, 2010 10:50 pm
by burger2227
You can use INKEY$ to clear the keyboard buffer before or after an INP(&H60) read.
This will clear the keyboard in QB64:
Code: Select all
DEF SEG = 0
DO 'program loop
i = INP(&H60) 'update keydown states
DO 'key read loop
IF (i AND 128) THEN KeyPress(i XOR 128) = 0
IF (i AND 128) = 0 THEN KeyPress(i) = -1
i2 = i
i = INP(&H60)
POKE 1050, PEEK(1052) 'clear keyboard buffer
LOOP UNTIL i = i2
'key read code
LOOP
DEF SEG
BTW, can you share your RPG code so that Galleon can test it?
You never answered...
Ted
Posted: Tue Nov 30, 2010 11:33 pm
by ThirtyNitesOfMX
i was still trying to understand how the first one works.
it didnt seem to help.
i implemented the function, used the if scankey%(x) then, else
used zerocodes% = ScanKey%(0) at the end of each sub before returning to the main loop
did not work. i will try the second thing you posted.
Posted: Tue Nov 30, 2010 11:34 pm
by ThirtyNitesOfMX
i did reply in the last thread, i said if you shoot me an email adress ill send the code. i will also have to send all the files its loading for him to run the program though
Posted: Wed Dec 01, 2010 12:27 am
by ThirtyNitesOfMX
thanks.. i figured it out. im a little confused though, why did you say you cant poke and peek with newer pc keyboards and then suggest that i poke and peek?
anyways, im assuming the keyboard buffer array is < 300 entries? i think i heard somewhere it was 255 or 155
i just let the first 300 times through the main loop and the first 300 times through every time i return back to it have no control over the keyup and keydown variables, and also set them all to up.. seems to work fine without any lag when returning to the main loop. thanks for your help.. i couldnt figure your code out but it helped me realize all i needed to do was clear the buffer manually.. its weird though that qbasic never has had a clear keyboard buffer command. or allow you to take temporary control over the keyboards repeat rate. anyways..
can qb64 read usb info? ive figured out a way to use a usb gamepad, but its probably not the best way, and if theres another way, im guessing you know it.
Posted: Wed Dec 01, 2010 2:22 am
by burger2227
There are 255 ASCII characters, but the keyboard only has about 101 keys. You can't POKE &H60 or use OUT &H60.
Since QB64 emulates POKEs Galleon allowed that to work. Many others do not work in QB64 yet.
I don't understand why you can't clear the keyboard buffer. An INKEY$ loop will clear it:
DO: K$ = INKEY$: LOOP UNTIL K$ = ""
The function can only clear the array that holds multiple press or release codes. Not the buffer. INKEY$ is used in the function to help clear the buffer so that it does not BEEP when it gets full.
No USB stuff yet either except for LPRINT with a USB printer.
Anyhow, my Email address is the same place yours is. Just click it or right click it to copy it!
Ted