Page 1 of 1

Are arcade games possible in QB? [answered]

Posted: Sun Nov 03, 2019 3:46 pm
by Alex
Is it possible to have real-time games with keyboard control in QB? I always wrote games that used mouse input or that didn't require real time control like RPGs and turn based games. Writing real time interfaces on 8-bit platforms was easy because you can poll the joystick and determine at any time if it is pressed a certain direction. Thus you can get as many samples per second as you need by polling that many times. But I've found on emulating a joystick with the cursor keys that is not the case with keyboard. Two problems come up. First, there is a lag after the key is pressed before it starts repeating. Second, it repeats at a fixed rate which is rather slow, on the order of 10 or 15 per second. This means that controlling an on screen sprite's movement is erratic. When the key is held down to continually move in one direction at first there is a single movement followed by a long delay followed by more movements, and unless each key poll results in moving many pixels it takes several seconds to move across even a small (320x200) screen. But moving several pixels could make it impossible to finely align the sprite with other on screen dangers. That's not fun in an arcade game if you can't pilot through the narrow tunnel or avoid the incoming shots because you can only move in big jerky movements.

So my question is how can one make arcade style games with real-time, fine-grained, player-controlled motion in QB? Is the mouse the ONLY option that everyone has or can we use the keyboard and if so how?

Re: Are arcade games possible in QB?

Posted: Tue Nov 05, 2019 9:24 am
by burger2227
INP(&H60) can be read into an array to do multiple key operations as demonstrated in the ping pong program here: http://www.qb64.net/wiki/index-php/INP/

Re: Are arcade games possible in QB?

Posted: Tue Nov 05, 2019 11:05 am
by Alex
Do you know of another example? That example is very poor. There is no text explanation of what the code does and it is uncommented. I don't see how that code could do what it is supposed to.

Re: Are arcade games possible in QB?

Posted: Tue Nov 05, 2019 11:47 am
by burger2227
The Function records every key press code position into the keyflags% array as -1 or 0 if the key was released so reading certain key codes will tell if those keys were pressed, even more than one to move diagonally for instance. Codes above 127 are release codes:

Code: Select all

FUNCTION ScanKey% (scancode%)
STATIC Ready%, keyflags%() ' ready = 0 re dims the array 
IF NOT Ready% THEN REDIM keyflags%(0 TO 127): Ready% = -1 'set up array
i% = INP(&H60) 'read keyboard states
IF (i% AND 128) THEN keyflags%(i% XOR 128) = 0 'key released
IF (i% AND 128) = 0 THEN keyflags%(i%) = -1 'key pressed
K$ = INKEY$ 'clears keboard buffer to prevent beeps
ScanKey% = keyflags%(scancode%) 'reads key code sent by program 
END FUNCTION  
Try Example 3 with key codes of keyboard listed: http://www.qb64.net/wiki/index-php/Scancodes/

Re: Are arcade games possible in QB?

Posted: Tue Nov 05, 2019 1:05 pm
by Alex
After throwing away my assumptions I think I've mostly figured it out. It does NOT update multiple keys at the same time. It gives each key a value from 1-127 and then each call updates ONE key press or release status and removes one key from the buffer and throws it away. What it still doesn't explain is if calling INP(&H60) reads the live status of the keyboard or if there is an event queue that it reads the next event from. If I mash down five keys at the same time and later release all the keys at the same time, how does INP(&H60) react? If I don't call this routine for a while and there have been multiple presses or both presses and releases in that time what does it report since it only updates 1 key status at a time?

I think properly done this routine should be split into two. One that updates the keyflags%() array and is called regularly like in every iteration of the main program loop, and one that checks the keyflags%() array to answer if the key the programmer is interested in is currently depressed. Function ScanKey%() seems to be doing exactly the same thing that QB64's _KEYDOWN() built-in function does but it works in QB/QBasic whereas _KEYDOWN is QB64-only.

Re: Are arcade games possible in QB?

Posted: Wed Nov 06, 2019 3:49 pm
by burger2227
That is why I posted those programs

Re: Are arcade games possible in QB?

Posted: Wed Nov 06, 2019 3:52 pm
by Alex
Thank you, burger2227.

Re: Are arcade games possible in QB? [answered]

Posted: Mon Dec 16, 2019 11:12 pm
by MikeHawk
Damn I'm late. If you're still interested, I'm going to shamelessly plug my page here (don't mind the URL, it covers joystick, mouse, AND keyboard):
https://qbmikehawk.neocities.org/articl ... index.html

Long story short: keyboards have no on-board memory. What they do is send ONE byte of information via port 0x60 whenever there's a key status CHANGE (a key has been pressed or has been released,) thus the value found at port 0x60 will remain the same until another status change happens. The data sent contains two sets of information: a scan code (bits 0 to 6) and the status change of the specified key (bit 7 - if set, the key has been released, if not set, the key has been pressed.) Your program will never be able to stay up-to-date on current key status because releasing multiple keys at once may rapid-fire data to port 0x60 while your program is busy (and therefore, won't catch the changes.)

The proper way to do it is by replacing the ISR (Interrupt Service Register) for keyboard handling (register 9, interrupt 0x21) on the BIOS level, because that interrupt is called whenever there's a change to port 0x60 (that's how iD Software did with Wolfenstein 3D.) In QBASIC, it used to be done by reserving memory via an array, writing an ASM program that would modify the content of that array according to port 0x60, and hijacking ISR9 so the ASM code would be called right when a keyboard change occurs.

Hope that helps.